在C(或C++)中,指针是特殊的,如果它们的值为零:我建议在释放内存后将指针设置为零,因为这意味着再次释放指针并不危险; 当我调用malloc时,如果它无法获取内存,则返回一个值为零的指针; 我一直用if (p != 0)它来确保传递的指针是有效的,等等.
但是,由于内存寻址从0开始,因此有效地址不是0吗?如果是这样的话,0如何用于处理空指针?为什么不是负数而是null?
编辑:
一堆好的答案.我将总结在所表达的答案中所说的内容,因为我自己的思想解释了它,并希望如果我误解,社区将纠正我.
就像编程中的其他一切一样,它是一种抽象.只是一个常量,与地址0并不真正相关.C++ 0x通过添加关键字来强调这一点nullptr.
它甚至不是地址抽象,它是C标准指定的常量,只要它确保它永远不等于"真实"地址,编译器就可以将它转换为其他数字,如果0不是,则等于其他空指针用于平台的最佳价值.
如果它不是抽象,早期就是这种情况,系统使用地址0,程序员不受限制.
我承认,我的负面数字建议是一个狂热的头脑风暴.对地址使用有符号整数有点浪费,如果它意味着除了空指针(-1或其他)之外,值空间在产生有效地址的正整数和刚刚浪费的负数之间均匀分配.
如果任何数字总是可以由数据类型表示,那么它就是0.(也可能是1.我想的是一位整数,如果是无符号则为0或1,或者只有符号的有符号位,或两位整数,将是[-2,1].但是你可以只得0为空,1是内存中唯一可访问的字节.)
还有一些东西在我的脑海里没有得到解决.Stack Overflow问题指向特定固定地址的指针告诉我,即使0表示空指针是抽象,其他指针值也不一定.这导致我发布另一个Stack Overflow问题,我是否可以访问地址零?.
我正在为地址0x0000有效且包含端口I/O的系统编写C代码.因此,访问NULL指针的任何可能的错误都将保持不被检测到,同时会导致危险的行为.
出于这个原因,我希望将NULL重新定义为另一个地址,例如一个无效的地址.如果我不小心访问了这样的地址,我将得到一个硬件中断,我可以处理错误.我碰巧有权访问此编译器的stddef.h,因此我实际上可以更改标准头并重新定义NULL.
我的问题是:这会与C标准发生冲突吗?据我所知,从标准中的7.17开始,宏是实现定义的.标准中的其他地方是否有任何内容表明NULL 必须为0?
另一个问题是,无论数据类型如何,大量编译器都会通过将所有内容设置为零来执行静态初始化.尽管标准规定编译器应将整数设置为零并将指针设置为NULL.如果我将为我的编译器重新定义NULL,那么我知道这样的静态初始化将失败.我是否可以将其视为不正确的编译器行为,即使我手动大胆地更改了编译器头?因为我确实知道这个特定的编译器在进行静态初始化时不访问NULL宏.
我一直在写类似的东西
char *x=NULL;
Run Code Online (Sandbox Code Playgroud)
假设是
char *x=2;
Run Code Online (Sandbox Code Playgroud)
会创建一个char指向地址2 的指针.
但是,在GNU C编程教程中,它表示int *my_int_ptr = 2;将整数值存储2到my_int_ptr分配时的任何随机地址.
这似乎意味着我自己char *x=NULL正在将NULL一个cast 的值分配给char内存中的某个随机地址.
而
#include <stdlib.h>
#include <stdio.h>
int main()
{
char *x=NULL;
if (x==NULL)
printf("is NULL\n");
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
事实上,印刷品
一片空白
当我编译并运行它时,我担心我依赖于未定义的行为,或者至少是指定不足的行为,我应该写
char *x;
x=NULL;
Run Code Online (Sandbox Code Playgroud)
代替.
我想传入一个硬编码的char数组作为sourcememcpy 的参数...像这样:
memcpy(dest, {0xE3,0x83,0xA2,0xA4,0xCB} ,5);
Run Code Online (Sandbox Code Playgroud)
使用clang编译时会出现以下错误:
cccc.c:28:14: error: expected expression
Run Code Online (Sandbox Code Playgroud)
如果我修改它(参见额外的括号):
memcpy(dest,({0xAB,0x13,0xF9,0x93,0xB5}),5);
Run Code Online (Sandbox Code Playgroud)
clang给出的错误是:
cccc.c:26:14: warning: incompatible integer to pointer
conversion passing 'int' to parameter of
type 'const void *' [-Wint-conversion]
cccc.c:28:40: error: expected ';' after expression
memcpy(c+110,({0xAB,0x13,0xF9,0x93,0xB5}),5);
Run Code Online (Sandbox Code Playgroud)
那么,问题是:
如何传入硬编码数组作为memcpy(http://www.cplusplus.com/reference/cstring/memcpy/)的源参数
我试过了:
(void*)(&{0xAB,0x13,0xF9,0x93,0xB5}[0]) - syntax error
{0xAB,0x13,0xF9,0x93,0xB5} - syntax error
({0xAB,0x13,0xF9,0x93,0xB5}) - see above
(char[])({0xE3,0x83,0xA2,0xA4,0xCB}) - error: cast to incomplete type 'char []' (clang)
Run Code Online (Sandbox Code Playgroud)
和一些更疯狂的组合我很惭愧写在这里......
请记住:我不希望创建一个新的变量来保存阵列.
这个问题旨在成为整数和指针问题之间所有初始化/分配的常见问题解答条目。
我想编写代码,将指针设置为特定的内存地址,例如0x12345678. 但是当用 gcc 编译器编译这段代码时,我得到“初始化使指针从整数而不进行强制转换”警告/错误:
int* p = 0x12345678;
Run Code Online (Sandbox Code Playgroud)
类似地,这段代码给出了“初始化从指针生成整数而不进行强制转换”:
int* p = ...;
int i = p;
Run Code Online (Sandbox Code Playgroud)
如果我在变量声明行之外做同样的事情,消息是一样的,但说的是“赋值”而不是“初始化”:
p = 0x12345678; // "assignment makes pointer from integer without a cast"
i = p; // "assignment makes integer from pointer without a cast"
Run Code Online (Sandbox Code Playgroud)
使用其他流行编译器的测试也会给出错误/警告消息:
int不能用于初始化类型的实体int*”int*在间接级别上与int”不同。问题:上面的例子是有效的 C 吗?
还有一个后续问题:
这不会给出任何警告/错误:
int* p = 0;
Run Code Online (Sandbox Code Playgroud)
为什么不?
我有一个任务.该程序将打印C中所有命令行参数的总和.我尝试编译它的代码,但在控制台中传递参数后抛出错误.下面是代码.
/* Printing sum of all command line arguments */
#include <stdio.h>
int main(int argc, char *argv[]) {
int sum = 0, counter;
for (counter = 1; counter <= argc; counter++) {
sum = atoi(sum) + atoi(argv[counter]);
}
printf("Sum of %d command line arguments is: %d\n", argc, sum);
}
Run Code Online (Sandbox Code Playgroud)
编译后显示Segmentation fault(core dumped)错误.您的经验可以解决我的问题.
以下是我编辑的代码:
/* Printing sum of all command line arguments*/
#include <stdio.h>
#include <stdlib.h> // Added this library file
int main (int argc, char *argv[]) {
int …Run Code Online (Sandbox Code Playgroud) 如果我减去两个void指针,我得到指针位置之间的相对距离(至少在我的测试系统上).我应该使用什么类型来存储结果,以便它与64位系统兼容?size_t是正确的类型还是长?
背景:我们需要检查给定的void指针是否可以安全地用作双指针.我们曾经将指针强制转换为int并检查低三位是否为零,但是我们当前的编码标准不再允许将指针转换为整数类型.我正在考虑计算void指针和NULL指针之间的差异,并检查该差异是否可以被8分割.假设NULL指针始终是8字节对齐的?
我想知道检查空值的最佳(我的意思是性能和正确)是什么?
我知道这两种方式:
首先(我认为最好的):
对于任何指针检查:
if (value == NULL) ...
Run Code Online (Sandbox Code Playgroud)
对于int:
if (value == 0) ...
Run Code Online (Sandbox Code Playgroud)
第二:
if (value) ...
Run Code Online (Sandbox Code Playgroud) 我很好奇为什么当我说我迭代地遍历链表时我必须做while (list != NULL)而不是while (!list).我认为NULL等于零或假.
来自评论:当我尝试一个while (!list)但从来没有前者时,我的程序似乎总是崩溃.每个节点都包含一个指向一段数据的void指针和一个指向下一个节点的指针.
是否有可能获得一个函数来返回一个int或一个char*取决于执行时发生的事情?我已经尝试了无效但在编译时我得到了很多警告
例
void int_char(char *str)
{
if (I 'm matching a condition in my string)
return (str);
else
return (0);
}
Run Code Online (Sandbox Code Playgroud)
我希望我足够清楚.PS:我是C编程的初学者
c ×10
pointers ×4
null ×2
alignment ×1
arrays ×1
atoi ×1
c++ ×1
casting ×1
hardcoded ×1
if-statement ×1
linked-list ×1
memory ×1
syntax-error ×1
void ×1