当前位置:首页 » 编程语言 » c语言指针问题

c语言指针问题

发布时间: 2022-08-22 08:47:00

1. c语言指针问题

你好,二者并不等价, 首先我们知道,a[i]是指向一个有20个char元素的char数组 而p是指向指针的指针
我们可以来分析啊 当你 p=a 时, p即a[0] [0] 的地址 此时你*p 即为取出a[0] [0] 的内容即为'a', 而当你 **p 的时候 就出错了, 这时候你就是在对 ‘a’ 这个字符取地址,这时候就会出现内存异常错误,你肯定是不能对97取地址。你可以强制转换赋值然后自己试一下 即可
p = (char **)a;

2. c语言中的指针问题

指针计算问题
首先分析***(pp+1)
因为pp是一个数组指针,也就是说pp里面中的每个元素都是一个指针,因此pp+1就是使指针pp指向数组中的下一下元素的地址,也就是&pp[1]的地址,那么后面的就好计算了***(pp+1)=***(&pp[1])=**pp[1]=*pp[1][0]=pp[1][0][0]很明显,就是二维数组指针第二行行一列的指针指向的第一个元素的值,也就是"mnopqr"字符串中的第一个字母m,注意一行有三个元素,"mnopqr"才是第二行。

**pp[0]的计算
**pp[0]=*pp[0][0]=pp[0][0][0]这很明显,是第一字符串中的第一个字母,也就是"abc"中的字母a

(*(*(pp+1)+1))[4]的计算
(*(*(pp+1)+1))[4]
=(*(*(&pp[1])+1))[4]
=(*(pp[1]+1))[4]
=(*(&pp[1][0]+1))[4]
=(*(&pp[1][1]))[4]
=(pp[1][1])[4]
=pp[1][1][4]

这就很明显了,结果是pp[1][1]这个指针指向的第5个元素,指针pp[1][1]指向的是"stuvw",其第5个元素就是w

*(pp[1][2]+2)的计算
*(pp[1][2]+2)
=*(&pp[1][2][0]+2)
=*(&pp[1][2][2])
=pp[1][2][2]
很明显是pp[1][2]指针指向的第3个元素,pp[1][2]指向的是字符串"xyz",因此第3个元素就是字母z

**(pp+1)的计算
**(pp+1)
=**(&pp[0]+1);
=**(&pp[1])
=*pp[1]
=*(pp[1])
=*(&pp[1][0])
=pp[1][0]
因此输出的是指针pp[1][0]所指向的字符串

如果你对以上的计算有不理解之处,请去本人文库下载文章《C++指针与动态分配内存new关键字专题》里面有关于指针和[]下标运算符混全运算的相当详细的讲解,文章中的计算法则适合于所有关于指针与[]的混合运算。

3. c语言指针问题

第一,指针类型的变量(以下称指针变量)是用来保存地址的,指针变量的类型决定了它可以保存哪种类型的变量的地址。char *s说明s可以用来保存一个char类型的变量的地址(char *是s的类型,说明s可以保存一个char类型的变量的地址)。
第二,s是指向c[0]的,即s保存的是c[0]的地址(s的值是c[0]的地址),对于A. printf("%s\n", s);%s说明是输出一个以'\0'结尾的字符串,字符串的起始地址在s中,而beijing只有7个字符,数组c分配了8个字节的空间,所以有空间容纳自动添加的'\0',所以A正确。
第三,*是用来说明s是指针类型的。

4. C语言中的指针问题

这样的"xxxx"应该叫做字符串常量,是存储在常量区域的,所以不应该修改它。
char a[]="don't know"
是定义了一个数组,数组内的数据复制了字符串的内容。
char *a="don't know"
第二种编译的时候就应该给你警告了,不能用非常量指针指向一个常量,应该是这样
const char *a="don't know"
所以不能通过指针改变它。

5. 关于C语言中的指针问题

同学你是没理解指针是什么意思。
Root = NULL的意思是将Root指向一处空的位置,这时候Root里面的一切都是空的(没有开辟内存空间),当运行到Root->data.value的时候,程序尝试读取Root里面的data元素,这时候就会出现读取内存越界,因为Root指向的地方是空(没有分配内存)。

6. C语言指针使用问题

答案没错的,是你理解错了,这里不是要把r替换为s。
重点看这段代码:
if(*p==ch)
{
*str=*p;
(*str)++;
str++;
}
这里的意思是当p指向的字符和ch相等时,将str所指向的字符变为ch,然后再++对应这里也就是先变为r然后变为s,str++表示str指向下一个字符。这里的str一开始是指向program中的p字符,然后当p指针指向r字符时,str还是指向p字符,接着str将p字符改为r,然后又++改为s。接着p指针继续向下移动,一直到第二个r,然而此时的str是指向program中的第二个元素也就是r,然后重复和之前一样的步骤变为s。最后跳出循环后,*str='\0';表示截断。
哦,还有就是你第一个程序写错了,scanf函数要的是指针,不是scanf("%c",char_c);这样的。char_c是个变量名,应该scanf("%c",&char_c);

That'all

7. c语言指针问题

C语言的大多语法都是简单易懂的,这常常会给初学者一种“别人都说C语言难,我看也不过如此”的感觉。但是这种感觉常常会停止在初学者学到指针时,这是一些读者跟我说的。

鉴于很多C语言初学者都觉得指针非常难,

小明定义了一个C语言函数 int f(int * ),为什么 f(&5) 不能正常工作呢?

如果希望传递 5 给函数 f(),在C99中,可以使用下面这种方法:

f( (int[]){5} );
上面这行C语言代码相当于定义了一个数组,并且数组只有一个元素 5,函数 f() 接收到的参数是该数组,只不过这一过程中的数组名没有“显示”。

抛开C99的这个特性,C语言调用 f(&5) 就不能这么写了,而是需要借助变量:

int five = 5;
f(&five);
在C语言中,接受某个值指针的函数是有可能通过该指针修改该值的(即使程序员无此打算,C语言还是会一直这么认为),因此只有变量才能胜任。在C语言中,常数是只读的,只能作为右值,& 运算符是不能处理常数 5 的,f(&five) 会引发编译错误。

f(&five) 会引发编译错误

表达式 * p++ 增加了 p 指向的数值,还是指针 p 本身?

C语言中的 ++ 和 — 运算符的优先级高于 * 运算符,所以 *p++ 其实就相当于 *(p++)。显然,++ 运算符增加的是指针 p 本身的值,不过在指针 p 自增之前,*p++会先返回 p 指向的值。如果希望 ++ 运算符增加 p 指向的值,应该使用括号运算符:(*p)++。

小明想使用指针操作数组里的数值,下面这段C语言代码有什么问题?

小明预计程序会输出 3,但是程序却输出了“垃圾值”,他的C语言代码如下,请看:

int array[5], i, *ip;
for(i = 0; i < 5; i++)
array[i] = i;
ip = array;
printf("%d\n", *(ip + 3 * sizeof(int)));

8. C语言指针问题

1、ptr赋值为arr地址后指向第一个元素,即元素6.
2、*(ptr++) += 123;由于是右侧操作(递增后缀),所以先取ptr地址后再递增ptr,此时取得的地址还是第一个元素地址(递增后ptr指向第二个元素,也就是7,这是第一次递增),因此是对6+123=129,并保存原地址,即第一个元素地址,因此6被改为129。
3、输出时,由于printf为了左对齐参数格式,必须从右到左处理参数入栈,由于++ptr为左侧操作,因此先递增ptr,ptr指向第三个元素,这是第二次递增,然后取值,那么显然读取的数据为8、入栈,然后再处理左侧参数*ptr,此时ptr没有递增还是指向8,因此取得的还是8,入栈。因此输出都是8

PS:进入函数后,先退栈取值得到第一个参数,也就是后入栈的函数左侧参数,输出,再退栈取得第二个参数,也就是先入栈的函数右侧参数,输出。

这类前后++--的题实际很简单,先搞清楚优先级就行了,也就是搞清楚执行先后,左侧++--优先级最高,比如 a*++b--这样的表达式,不用看肯定是++优先,先处理++b再与a相乘,还比如a+++b,表达式解析时是从左到右,所以先判断为a的右侧操作,所以先取值后递增,取值后再与b相加。
其二,递增递减操作在变量左侧的会立刻影响当前取值,因为它是先运算再取值,而在右侧操作的会影响后续代码的变量取值,但不改变当前对变量的取值,因为在递增递减前当前取值已经完成。

9. c语言 指针问题

指针的声明与初始化
1、不恰当的指针声明
考虑如下的声明:
int* ptr1, ptr2; // ptr1为指针,ptr2为整数

正确的写法如下:
int* ptr1, *ptr2;

用类型定义代替宏定义是一个好的习惯,类型定义允许编译器检查作用域规则,而宏定义不一定会。
使用宏定义辅助声明变量,如下所示:
#define PINT int*
PINT ptr1, ptr2;

不过结果和前面所说的一致,更好的方法是使用下面的类型定义:
typedef int* PINT;
PINT ptr1, ptr2;

2、使用指针未初始化
在使用指针之前未初始化会导致运行时错误,如下面的代码:
int* p;
...
printf("%d\n", *p);

指针p未被初始化,可能含有垃圾数据
3、处理未初始化指针
总是用NULL来初始化指针
用assert函数
用第三方工具
把指针初始化为NULL更容易检查是否使用正确,即便这样,检查空值也比较麻烦,如下所示:
int *pi = NULL;
...
if(pi == NULL) {
//不应该解引pi
} else {
//可以使用pi
}

我们可以使用assert函数来测试指针是否为空值:
assert(pi != NULL);

指针的使用问题
缓冲区溢出
缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,使得溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所使用的缓冲区又被称为”堆栈”.。在各个操作进程之间,指令会被临时储存在”堆栈”当中,”堆栈”也会出现缓冲区溢出。
下面几种情况可能导致缓冲区的溢出:
访问数组元素时没有检查索引值
对数组指针做指针算术运算时不够小心
用gets这样的函数从标准输入读取字符串
误用strcpy和strcat这样的函数
1、测试NULL
使用malloc这样的函数的时候一定要检查返回值,否则可能会导致程序的非正常终止,下面是一般的方法:
float *vector = malloc(20 * sizeof(float));
if(vector == NULL) {
//malloc分配内存失败
} else {
//处理vector
}

2、错误使用解引操作
声明和初始化指针的常用方法如下:
int num;
int *pi = #

下面是一种看似等价但是错误的声明方法:
int num;
int *pi;
*pi = #

3、迷途指针
参见《C迷途指针》
4、越过数组边界访问内存
没有什么可以阻止程序访问为数组分配的空间以外的内存,下面的例子中,我们声明并初始化了三个数组来说明这种行为:
#include<stdio.h>
int main()
{
char firstName[8] = "1234567";
char middleName[8] = "1234567";
char lastName[8] = "1234567";
middleName[-2] = 'X';
middleName[0] = 'X';
middleName[10] = 'X';
printf("%p %s\n", firstName, firstName);
printf("%p %s\n", middleName, middleName);
printf("%p %s\n", lastName, lastName);
return 0;
}

热点内容
电信路由器密码设置无线路由器怎么设置密码 发布:2024-05-18 10:55:00 浏览:647
安卓系统是属于哪个国家的手机 发布:2024-05-18 10:41:41 浏览:99
linux运维前景 发布:2024-05-18 10:24:44 浏览:658
c语言crc算法 发布:2024-05-18 09:59:03 浏览:644
linuxc编程视频 发布:2024-05-18 09:55:58 浏览:273
如何建造一个好的服务器 发布:2024-05-18 09:54:30 浏览:524
编译原理中的左结合 发布:2024-05-18 09:42:00 浏览:26
怎样加密路由器 发布:2024-05-18 09:41:55 浏览:605
百度云不能上传视频了 发布:2024-05-18 09:41:08 浏览:148
mac适合买大存储 发布:2024-05-18 08:30:08 浏览:583