user-0 提问: 运行报段错误，指针操作问题

回复:
user: user-0
content: 引用 10 楼 hhhhhhhhhhkkkkkkkkkk 的回复:你用的是GCC吧？如果你用VS2013来把代码复制进去，你会发现所有与int*p=3相关的都被画了红线（出错色）：  这里是我说的错误处：   这里是因为在func里int i,*p;引发的指针级别错误，应该改为:  int i,**p;    十分感激，问题已经找到并成功运行了。 修改后代码如下：  #include <stdio.h> #include <string.h>  void func (int *num,int *a, long *b, char *c) { 	int i,**p; 	int i_t=5; 	long l_t=10; 	int j=3; 	 	p=# 	for(i=0;i<3;i++) 	{ 		p--; 		if(i==0) memcpy(*p,&i_t,sizeof(int)); 			else if(i==1) memcpy(*p,&l_t,sizeof(long)); 				else memcpy(*p,"hello!",6); 	}  	return ; }    int main (void) { 	int i_s=1; 	long l_s=1; 	char c_s[10]; 	int t=3; 	int *p; 	p=&t; 	memset(c_s,0,sizeof(c_s));  	func(p,&i_s, &l_s, c_s); 	printf("a = %d\n,b = %d\n,c = %s\n",i_s, l_s, c_s); 	return 0; }   感谢hk和赵老师的回答，关于指针这块要学的还有很多，谢谢

user: user-1
content: 当我把这两个地方的语法错误都改好后：  void func(int *num, int *a, long *b, char *c) { 	int i, **p; 	int i_t = 5; 	long l_t = 10; 	int j = 3;  	p = # 	memcpy(a, &i_t, sizeof(int)); 	printf("a=%d\n", *a); //测试 	for (i = 0; i<3; i++) 	{ 		p -= 2; 		if (i == 0) memcpy(*p, &i_t, sizeof(int)); 		else if (i == 1) memcpy(*p, &l_t, sizeof(long)); 		else memcpy(*p, "hello!", 6); 	} 	return; }  int main(void) { 	int i_s = 1; 	long l_s = 1; 	char c_s[10]; 	int *p = (int*)3; 	memset(c_s, 0, sizeof(c_s));  	func(p, &i_s, &l_s, c_s); 	printf("a = %d\n,b = %d\n,c = %s\n", i_s, l_s, c_s); 	return 0; } ] 运行，就会引发访问冲突，这是因为程序不准你随便看内存上其他地方(这里是地址3那里)的东西，如果你能随便看，那密码什么的都不再是密码了，你想怎么看就怎么看，这怎么能行呢是吧：

user: user-1
content: 你用的是GCC吧？如果你用VS2013来把代码复制进去，你会发现所有与int*p=3相关的都被画了红线（出错色）：  这里是我说的错误处：   这里是因为在func里int i,*p;引发的指针级别错误，应该改为:  int i,**p;

user: user-0
content: 引用 7 楼 hhhhhhhhhhkkkkkkkkkk 的回复:[quote=引用 2 楼 yzg001212 的回复:] [quote=引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题[/quote] 就是因为你那里将p直接赋为3，传给func的参数num的也是3，你又在func里定义了另一个p来使用这个参数num，所以func里的p还是3，也就是你直接把p赋给了常数，这是违法的。[/quote]  你说的原因不是导致我程序报错的问题，我修改后还是报错。 修改内容： int t=3; p=&t;

user: user-0
content: 引用 6 楼 zhao4zhong1 的回复:进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令  GNU gdb Fedora (6.8-37.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu"... Reading symbols from /lib64/libc.so.6...done. Loaded symbols for /lib64/libc.so.6 Reading symbols from /lib64/ld-linux-x86-64.so.2...done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 Core was generated by `./test'. Program terminated with signal 11, Segmentation fault. [New process 11990] #0  0x0000000000400577 in func (num=0x7fff2278677c, a=0x7fff227867a4, b=0x7fff22786798, c=0x7fff22786780 "") at test.c:19 19                      if(i==0) memcpy(*p,&i_t,sizeof(int)); (gdb) bt #0  0x0000000000400577 in func (num=0x7fff2278677c, a=0x7fff227867a4, b=0x7fff22786798, c=0x7fff22786780 "") at test.c:19 #1  0x000000000040065e in main () at test.c:44  这是我执行后产生的结果，但是我还是没看出来问题，能麻烦赵老师在指导一下吗

user: user-1
content: 引用 2 楼 yzg001212 的回复:[quote=引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题[/quote] 就是因为你那里将p直接赋为3，传给func的参数num的也是3，你又在func里定义了另一个p来使用这个参数num，所以func里的p还是3，也就是你直接把p赋给了常数，这是违法的。

user: user-2
content: 进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

user: user-2
content: 3楼代码中的注释已经讲的足够清楚了。

user: user-0
content: 关于这段代码的个人见解： func的4个参数依次入栈，p先指向栈中存放num的地址，然后进行偏移，指向存放参数a的地址， 这时候执行memcpy函数的时候*p表示取指针a所指向的地址在进行赋值。 不知道什么原因这里报段错误，我用gdb调试时发现p的地址就是存放参数a的地址。希望有大神能给我指导一下

user: user-2
content: #include <stdio.h> #include <string.h>  void func (int *num,int *a, long *b, char *c) {     int i,*p;     int i_t=5;     long l_t=10;     int j=3;      p=#//此处将p的值赋值为main中变量p的地址，=左边的类型为int *,=右边的类型为int **,两边类型不匹配     memcpy(a,&i_t,sizeof(int));     printf("a=%d\n",*a); //测试     for(i=0;i<3;i++)     {         p-=2;//将p的值-2,因为p的类型为int *,假定sizeof(int)为4，p的值变为“main中变量p的地址-2*4”         if(i==0) memcpy(*p,&i_t,sizeof(int));//往地址“main中变量p的地址-2*4”处写值？！             else if(i==1) memcpy(*p,&l_t,sizeof(long));                 else memcpy(*p,"hello!",6);     }     return ; }  int main (void) {     int i_s=1;     long l_s=1;     char c_s[10];     int *p=3;//定义一个变量p，类型为int *，并初始化其值为3     memset(c_s,0,sizeof(c_s));       func(p,&i_s, &l_s, c_s);     printf("a = %d\n,b = %d\n,c = %s\n",i_s, l_s, c_s);     return 0; }  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

user: user-0
content: 引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:引用int *p=3; 这里不能把指针直接赋给常数的。  这步没有报错，问题不是这个，主要是在memcpy(*p,&i_t,sizeof(int)); 这步，p指针的问题

user: user-1
content: 引用int *p=3; 这里不能把指针直接赋给常数的。