指针的一个小问题 大神们教教

同的 请问哪不同图片说明

Student s1 = (Student)a;和Student s1 = (Student)a 貌似没有什么不同
看不懂你的理解
Student s1 = *(Student)a;
Student s2 = (Student)b;
这两句 我是这样理解的 你的参数是两个指针 一个a 一个b

student 本身就是一个类型 所以 student s1 = *(student)a 应该是 把a 转换成 student类型的指针 然后 取出 a存储的地址中的值 给s1
Student s2 = (Student)b; 是把b 转换成student类型的指针 然后 直接把b里面存储的地址当作值 给s2

student s1 = *(student)a ,应为a的类型是const void *,首先转换成student类型,在取a中存储的地址的值,应该是a.ID中存储地址的值
Student s2 = (Student)b; 是把b 转换成student类型的指针 ,然后s2 的类型可以与就与(Student)b的类型一样。可以相互赋值

Student s1 = *(Student)a;
Student s2 = (Student)b;

这两个都编译不过。

Student s1=*(Student *)a;

(Student *) 是强制类型转换,因为是指针类型 括号内要有 *

补充一下,下面的写法能够编译通过
Student s1 = (Student)a;
Student s2 = (Student)b;

C++类型转换要比C严格的多,但我不确定楼主的写法能C下能通过不。

这个能编译过

    Student s1 = *(Student*)a;
    Student *s2 = (Student*)b;

看到了更新后的题目,泪奔啊,怪不得头有点错呢。
但我想意思已经表达清楚了。

这段代码编译成功,指针类型的显式转换。

  Student s1 = *(Student*)a;

这段代码编译失败,编译器会把 把指针a 转换成结构SStudent时失败

 Student s1 = *(Student)a;

这里Student本身就是一个指针 类型为 1Student *
(Student )a表示把a强制转换为Student *类型的,即1Student *类型
(Student *)a取值之后的值应该是1Student *(*)
从数组的角度来看,这个值应该是一个二维数组的行指针,即是一个数组指针,指向一个数组
(Student)a的类型应该是1Student *,
从数组的角度来看,这个值是指向一维数组的指针,指向的是元素

希望不要误人子弟,不保证正确,嘻嘻

承认student本来就是指针,但是你的a也是一个指向student的指针,你根本就不能把一个把一个指向指针s的指针a强制转换成指针s,这和你不能将一个指向一个整形数据的指针强制转换成一个整整型数据类型是一个道理,即便他们两个都是指针,你也应该能够看出来肯定不能兼容。不同类型的指针,虽然都是存放地址,但不同类型的大小不同,这样转换会很容易出错。

typedef struct 1Student *Student;

这一行的意思是把指针类型“struct 1Student ”的类型名重新命名为Student。
所以“Student a;”相当于定义了一个学生类型的指针a,也就是和“struct 1Student *a;”这个句子是一个意思。
你的代码里面Student a[2];定义了一个数组,这个数组有两个元素,而且每个元素都是一个Student类型的变量。也就是说每个元素都是一个学生类型的指针。
你的comp函数里面,(Student
)a相当于把学生类型指针强制转换为一个二重指针,也就是指向另一个指针的指针,所以不对。
comp里面应该是像下么这么写:
struct 1Student s1=*(Student)a; //赋值号左边是定义了学生类型的变量,右边是先把空类型指针变为学生类型指针然后加*号在前面取得指针对应变量的值。接着再做赋值操作。

(student)不能过,我的理解是,只能同一层的指针进行转换,因为student是1student ,a也是1student *,但用了student就是1student的双指针
,不能将单指针转双指针,所以是类型转换过程就有问题,也就是(student*)这一步

加星号是不能过的,因为这样相当于单指针转双指针了,在c++是这样的。

typedef struct 1Student *student;

这条语句是 把 struct 1Student 这个结构的指针类型简写为 student , 这样 student 现在就代表 1Student 结构的指针这种类型

a 是 void* 类型,c语言对类型转换不严格,可以把void* 类型转换为任意指针类型,这在c++中是不可以的,这个要注意

既然a是void* 类型,他是指针,不是指针的指针,而 Student 本来就是指针, Student* 就是指针的指针
Student s1 = (Student)a 意思是 把a 转换成 Student* 类型,再取指向内存的内容, 这是错误的, ** 指针 和 指针的指针不是一个类型**
Student s2 = (Student)b 这么写就对了, 把 void* 转换为 Student 所代表的 1Student* 类型 再赋给相同类型的 s2

所以是不同的,第一种写法编译器会报错,一般错误描述应该是 不能把 void* 类型 转换为 1Student** 类型

Student s1 = *(Student *)a;
Student s1 = (Student)a;
一个是*a,一个是a,这两个显然是不同的意思
至于为什么可以去掉类型转换来区分,是因为对a的类型转换不改变a变量所保存的地址值,那么先把类型转换去掉就很容易看明白了

方法一是const void*显式转换为Student*后之后通过*运算符获得形参的值,这种转换更可靠更安全。方法二Student s1 = (Student)a;是不同类型的强制转换很有可能编译器不支持或者转换失败。

先了解形参和实参,了解什么是值传递和指传递

Student s1 = (Student)a; 将a强制转换为student指针类型的指针,再取首地址的内容
Student s2 = (Student)b; 将b强制转换为student类型的指针
这是我的理解

前面说法有误,看了下反汇编:

            Student s1 = *(Student *)a; //这里赋值错误,
00FB17BE  mov         eax,dword ptr [a]  
00FB17C1  mov         ecx,dword ptr [eax]  
00FB17C3  mov         dword ptr [s1],ecx  
    Student s2 = (Student)b;       //这里赋值正确
00FB17C6  mov         eax,dword ptr [b]  
00FB17C9  mov         dword ptr [s2],eax  

你的typedef用的有问题吧 应该写成 typedef struct lstuudent { }student:

首先说编译通过的原因。
虽然可能你的文件是cpp,不过这是纯C代码,你的函数comp的参数又都是const void *,所以编译器没有足够的信息进行类型检查。也就是你可以将这两个指针强制转换成任意指针类型,编译器都不会报错,甚至连警告都不会有。
然后看看函数怎么运行。
1,你定义的类型Student是个struct lStudent指针;
2,Student a[2]; a是一个Student类型数组,32bit情况下占用8个字节,a[0]和a[1]都是Student类型,分别占用4个字节,各自指向一个struct lStudent;
3,调用comp(a[0], a[1]); 因为C函数都是值传递,所以形参a、b就是a[0]、a[1]的值,可以说a、b都是Student类型,各自指向一个struct lStudent;
4,如果你写成Student s1 = (Student *)a; 意思是将a强制转化成Student \然后取其值;到这里你就能感觉到出问题了吧?将Student类型强转成Student *类型?运行到这里,32bit的CPU实际上会将a->ID(a->ID的地址和a是一样的)当成一个指针,然后取其指向的内存的4个字节赋值给s1,这个指令很大几率会崩溃,除非a->ID的值恰好指向一块可读内存。
5,Student s1 = (Student)a; 是正确的写法,这里告诉编译器将a视为一个Student类型并将值传递给s1.

实际上C语言只要确保取地址和取值两个操作的对应就好。比如你的这个函数其实怎么写都行,不过要和调用方式搭配好。
如果你想使用Student s1 = *(Student *)a; 那么调用是就要这样comp(&a[0], &a[1]); 这样加一次&操作,正好能抵消函数中多出一个*操作,结果还是正确的。

不过这种编程习惯很不好,函数comp的形参定义还是越清晰越好,比如:
int comp(const Student a, const Student b);
这样不需要在函数内进行强制转换,如果传参有什么问题,编译器就会检测到了。

a = 你传过来的student 类型的变量 a应该是变量的地址
Student s1 =
(Student *)a 这个先转变地址a的类型 再指向变量
Student s1 = (Student)a 这个将变量的地址 转为变量 不太搭吧

假如 void * a = b; // int b;
int c= int(a) 正确么? 一个是指针 一个是变量
假如 int * a = b; // int b;
int c= int(a) 正确么? 一个是指针 一个是变量

首先我们来看看,typedef 以后我们的数组成员是什么,当然,是指针,那么当函数内a,b都是数组元素的话,他们的类型都是结构体指针类型的,而,实际上,在C语言里面,所有的指针再同平台环境下,大小都是一样的,不管几重,不管基础类型,所以直接(Studen * )即可,前面没有必要解引用了。

这两种其实最终结果一样,但是在机器内表现方式不一样。

*(student *)a,这个a你可以看成地址,将在这个地址转换成指向student 指针的地址,此时a存放的是指向student的指针,
因此最终应用也是student类型。

(student)a,是直接将a这个地址转换成student的地址。