我一直认为像< code>const int *a这样的语句意味着< code>a是指向< code>const数据的< code>int指针,因此不能修改它所指向的值。事实上,如果您< code>const int a [] = {1,2,3}然后发出< code>a[0] = 10,您将会得到编译器错误。
然而,令我惊讶的是,以下编译没有任何警告并且运行良好。
#include <stdio.h>
#include <string.h>
int main (){
const int a [] = {1, 1, 1};
const int b [] = {2, 2, 2};
memcpy((void*) &a[0], (const void*)&b[0], 3*sizeof(int));
int i;
for (i=0; i<3; i++) printf("%d\n",a[i]);
return 0;
}
为什么允许这样做?这是因为演员阵容吗?当我这么做时(
cpy.c: In function ‘main’:
cpy.c:9:3: warning: passing argument 1 of ‘memcpy’ discards ‘const’ qualifier from pointer target type [enabled by default]
/usr/include/string.h:44:14: note: expected ‘void * __restrict__’ but argument is of type ‘const int *’
强制转换通常会禁止警告。有一个gcc选项-wcast-qual
会警告您强制转换丢失了const
或易失性
限定符。
程序成功运行,因为用于存储数组的内存实际上不是只读的,因为它们是在堆栈上分配的。这是一个实现细节,从技术上讲,如果实现非常严格,代码可能会崩溃。
将< code>a和< code>b声明为全局变量,它崩溃的可能性会更大(但仍不能保证)
强制转换到void*
删除与int
的关联-通过丢弃类型,您丢弃了类型装饰器,例如const
编辑
从下面的讨论中,我想弄清楚,重要的部分不是你投了什么(OQ中的void*
),而是你投了什么——这意味着扔掉你的原始类型及其装饰器。
您告诉编译器在执行强制转换时忽略初始声明。它倾听了。但这并不意味着你的程序是正确的。修改最初声明为const
的内容会导致未定义的行为(例如,编译器可以将该数据存储在只读内存中)。
C不会牵着你的手。如果你选择做一些危险的事情,它会让你得逞。
6. 指向指针的指针与指针数组 指针可以指向基本类型,也可以指向复合类型,因此也可以指向另外一个指针变量,称为指向指针的指针。 int i; int *pi = &i; int **ppi = π 这样定义之后,表达式*ppi取pi的值,表达式**ppi取i的值。请读者自己画图理解i、pi、ppi这三个变量之间的关系。 很自然地,也可以定义指向“指向指针的指针”的指针,但是很少用到: int
一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个 指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是 函数指针。 函数指针的定义形式为: returnType (*pointerName)(param list); returnType
主要内容:关于数组指针的谜题数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。以 为例,该数组在内存中的分布如下图所示: 定义数组时,要给出数组名和数组长度,数组名可以认为是一个 指针,它指向数组的第 0 个元素。 在C语言中,我们将第 0 个元素的地址称为数组的首地址。以上面的数组为例,下图是 arr 的指向:
指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为 二级指针,或者 指向指针的指针。 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示: 将这种关系转换为C语言代码: 指针变
在下面给出的代码中,我声明了一个指向int的指针,我们都知道memcpy返回一个指向目标字符串的空指针,所以如果ptr是指向int的指针,那么为什么printf(“%s”,ptr);是完全有效的,ptr毕竟不是指向char的指针。
在print语句中:(假设整数大小为4字节) 让arr的内存位置为1000 arr 1——给出1016(即下一行内存) 我理解了逻辑,但我无法理解编译器如何将 arr标识为“指向4整数数组的指针”,并且 即使在增量之前两者都指向相同的地址(1000)