相关二级指针引发的对类型赋值的考虑
有关二级指针引发的对类型赋值的考虑
#include<stdio.h>
int main(){
char *a[4];
char **p;
a[0] = "bai";
a[1] = "abc";
a[3] = "123";
p = &a[1];
//*p = *&a[1];为何不行?
printf("%s,%s,%s\n",*a,a[1],*a+2);
printf("%s,%s\n",*p ,*p+1);//对应**p
return 0;
}
* 是个规则。我想把规则和数值一块赋值过去但显然失败了;
如果你看不懂,那就下面这个问题:
int变量赋值是怎么把数值和大小规定赋值过去的
------解决方案--------------------
p = &a[1];
则结果是
p-->a[1]-->"abc" //这里a[1]是指向字符的指针
否则
p是个”野指针“(未赋值)
*p = *&a[1];
是向”野指针“指向的位置传指针----可以吗?
------解决方案--------------------
int变量赋值是怎么把数值和大小规定赋值过去的
类型啊!
编译器编译时对
变量=表达式
的处理是(根据代码中声明,在变量的定义域范围内记忆类型相关的信息)
生成表达式对应的计算过程代码,得到表达式的值(不论它是什么类型的),再按=左边变量的类型赋值(类型相同则直接传送变量对应的存储位置;类型不同由先做类型变换、变换成=左边变量的类型再传送)生成代码
------解决方案--------------------
char **p;
因为p没有指向任何空间.
使用 *p 解引用, 那出错是肯定的了.
还有, 你觉得 *&a[1] 这样不蛋疼吗. 取地址后马上又解引用
------解决方案--------------------
指针的类型需要赋值过去么
注意“指针”并不是一种变量类型
“int指针” 或 “char指针” 这些才是变量类型
“int指针” 和 “char指针” 之间的关系,就像int 和 char的关系一样,是完全两种类型的变量,没有什么关系
------解决方案--------------------
接上," &a[1] " 这个东西,并不只是一个地址,它是一个有类型的量,它的类型是【char *】
所以你如果这样写:
是会报错的,因为左边的类型是【char *】而右边的类型是【int *】,类型不同不能赋值,必须改成(char *)&a,强制转换才行
这样说理解了么
------解决方案--------------------
首先你要让p指向一个数据,p就不能是null,一定要有个地址吧、来保存你所要保存数据的地址
而你就是定义了一个 char **p;你没给他地址,你malloc一个就没问题了
------解决方案--------------------
指针类型的赋值表达式是要求严格类型一致的。
即=左边的指针变量的类型和=右边的表达式结果类型应该一致
编译器在编译过程中严格地检查这一点
如
char *p;
char a[N];
p=a; //左边的p是char*类型的,a实际上是&a[0],即指向首元素的指针,也是char*类型的
p=a+i; //左边的p是char*类型的,a+1实际上是&a[i],即指向字符元素的指针,也是char*类型的
所以,=左右的指针类型不一致时,又要完成赋值,程序员自己要写出强制类型转换,即=右边应该(type*)指针表达式
除了一种特殊情况外,仅当=左边是void*类型的指针变量时,可以不对右边的指针表达式做强制类型转换
代码中类型的检测、控制是编译器来做的
总结一下:
1.基本数据类型的赋值表达式,系统可以自动完成类型转换----程序员没做、编译器做----隐式类型转换
2.指针类型的赋值表达式,编译器严格检测、控制----必须由程序员来明确说明类型转换----显式或强制类型转换
------解决方案--------------------
类型是什么?许多教程说不出来,只说此种类型的数值占几个字节。
其实,类型是一类数据的编码格式,及所允许的相关操作。
如int的整型数据和double的双精度浮点数据,编码格式不同(字节数自然可能不同),double数据不允许%运算。
又如各种指针数据类型(除void*外),只允许有限的算术运算:
指针+(或-)整型数据(结果是同类型的指针)、指针-指针(同类型指针的减,结果是整型的)
指针不允许*,/,%运算
------解决方案--------------------
不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质,
而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。
我不喜欢不听话的孩纸!
------解决方案--------------------
#include<stdio.h>
int main(){
char *a[4];
char **p;
a[0] = "bai";
a[1] = "abc";
a[3] = "123";
p = &a[1];
//*p = *&a[1];为何不行?
printf("%s,%s,%s\n",*a,a[1],*a+2);
printf("%s,%s\n",*p ,*p+1);//对应**p
return 0;
}
* 是个规则。我想把规则和数值一块赋值过去但显然失败了;
如果你看不懂,那就下面这个问题:
int变量赋值是怎么把数值和大小规定赋值过去的
------解决方案--------------------
p = &a[1];
则结果是
p-->a[1]-->"abc" //这里a[1]是指向字符的指针
否则
p是个”野指针“(未赋值)
*p = *&a[1];
是向”野指针“指向的位置传指针----可以吗?
------解决方案--------------------
int变量赋值是怎么把数值和大小规定赋值过去的
类型啊!
编译器编译时对
变量=表达式
的处理是(根据代码中声明,在变量的定义域范围内记忆类型相关的信息)
生成表达式对应的计算过程代码,得到表达式的值(不论它是什么类型的),再按=左边变量的类型赋值(类型相同则直接传送变量对应的存储位置;类型不同由先做类型变换、变换成=左边变量的类型再传送)生成代码
------解决方案--------------------
char **p;
因为p没有指向任何空间.
使用 *p 解引用, 那出错是肯定的了.
还有, 你觉得 *&a[1] 这样不蛋疼吗. 取地址后马上又解引用
------解决方案--------------------
指针的类型需要赋值过去么
注意“指针”并不是一种变量类型
“int指针” 或 “char指针” 这些才是变量类型
“int指针” 和 “char指针” 之间的关系,就像int 和 char的关系一样,是完全两种类型的变量,没有什么关系
------解决方案--------------------
接上," &a[1] " 这个东西,并不只是一个地址,它是一个有类型的量,它的类型是【char *】
所以你如果这样写:
int a;
char* p=&a;
是会报错的,因为左边的类型是【char *】而右边的类型是【int *】,类型不同不能赋值,必须改成(char *)&a,强制转换才行
这样说理解了么
------解决方案--------------------
首先你要让p指向一个数据,p就不能是null,一定要有个地址吧、来保存你所要保存数据的地址
而你就是定义了一个 char **p;你没给他地址,你malloc一个就没问题了
------解决方案--------------------
指针类型的赋值表达式是要求严格类型一致的。
即=左边的指针变量的类型和=右边的表达式结果类型应该一致
编译器在编译过程中严格地检查这一点
如
char *p;
char a[N];
p=a; //左边的p是char*类型的,a实际上是&a[0],即指向首元素的指针,也是char*类型的
p=a+i; //左边的p是char*类型的,a+1实际上是&a[i],即指向字符元素的指针,也是char*类型的
所以,=左右的指针类型不一致时,又要完成赋值,程序员自己要写出强制类型转换,即=右边应该(type*)指针表达式
除了一种特殊情况外,仅当=左边是void*类型的指针变量时,可以不对右边的指针表达式做强制类型转换
代码中类型的检测、控制是编译器来做的
总结一下:
1.基本数据类型的赋值表达式,系统可以自动完成类型转换----程序员没做、编译器做----隐式类型转换
2.指针类型的赋值表达式,编译器严格检测、控制----必须由程序员来明确说明类型转换----显式或强制类型转换
------解决方案--------------------
类型是什么?许多教程说不出来,只说此种类型的数值占几个字节。
其实,类型是一类数据的编码格式,及所允许的相关操作。
如int的整型数据和double的双精度浮点数据,编码格式不同(字节数自然可能不同),double数据不允许%运算。
又如各种指针数据类型(除void*外),只允许有限的算术运算:
指针+(或-)整型数据(结果是同类型的指针)、指针-指针(同类型指针的减,结果是整型的)
指针不允许*,/,%运算
------解决方案--------------------
不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质,
而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。
我不喜欢不听话的孩纸!
------解决方案--------------------
1: //#include<stdio.h>
2: int main(){
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,58h
00401016 push ebx
00401017 push esi
00401018 push edi
3: char *a[4];
4: char **p;
5: void *pv;
6:
7: a[0] = "bai";
00401019 mov dword ptr [ebp-10h],offset string "bai" (00413024)
8: a[1] = "abc";
00401020 mov dword ptr [ebp-0Ch],offset string "abc" (00413020)
9: a[3] = "123";
00401027 mov dword ptr [ebp-4],offset string "123" (0041301c)
10:
11: p = &a[1];
0040102E lea eax,[ebp-0Ch]
00401031 mov dword ptr [ebp-14h],eax
12: //*p = *&a[1];为何不行?
13:
14: //printf("%s,%s,%s\n",*a,a[1],*a+2);
15: pv=(void *)(*a);
00401034 mov ecx,dword ptr [ebp-10h]
00401037 mov dword ptr [ebp-18h],ecx
16: pv=(void *)(a[1]);
0040103A mov edx,dword ptr [ebp-0Ch]
0040103D mov dword ptr [ebp-18h],edx