我们现在拥有许多新功能的C++ 11.一个有趣且令人困惑的(至少对我来说)是新的nullptr
.
嗯,不再需要令人讨厌的宏了NULL
.
int* x = nullptr;
myclass* obj = nullptr;
Run Code Online (Sandbox Code Playgroud)
尽管如此,我还没有得到如何nullptr
运作.例如,维基百科的文章说:
C++ 11通过引入一个new 关键字作为一个区分空指针常量来解决这个问题:nullptr.它的类型为nullptr_t,它是可隐式转换的,可与任何指针类型或指向成员类型的类型相媲美.除了bool之外,它不可隐式转换或与整数类型相比.
它是一个关键字和一个类型的实例?
另外,你有另一个例子(在维基百科旁边)哪里nullptr
优于好老0
?
我问,因为在这个帖子中引发了讨论.
尝试在其他人的回复下使用评论进行严肃的来回讨论并不容易或有趣.所以我想听听我们的C专家的想法,一次不限制500个字符.
C标准几乎没有什么可说的NULL
和空指针常量.我只能找到两个相关部分.第一:
3.2.2.3指针
具有值0的整型常量表达式,或者类型为void*的表达式,称为空指针常量.如果为指针的相等性分配或比较空指针常量,则将常量转换为该类型的指针.这种称为空指针的指针保证与指向任何对象或函数的指针不相等.
第二个:
4.1.5通用定义
宏是
Run Code Online (Sandbox Code Playgroud)NULL
它扩展为实现定义的空指针常量;
问题是,可以NULL
扩展为实现定义的空指针常量,该常量与3.2.2.3中列举的那些不同吗?
特别是,它可以定义为:
#define NULL __builtin_magic_null_pointer
Run Code Online (Sandbox Code Playgroud)
甚至:
#define NULL ((void*)-1)
Run Code Online (Sandbox Code Playgroud)
我对3.2.2.3的解释是,它指定0的整数常量表达式和0强制转换为类型void*的整型常量表达式必须是实现可识别的空指针常量的形式,但它不是意思是一份详尽的清单.我相信实现可以自由地将其他源构造识别为空指针常量,只要没有其他规则被破坏.
例如,可以证明这一点
#define NULL (-1)
Run Code Online (Sandbox Code Playgroud)
不是法律定义,因为在
if (NULL)
do_stuff();
Run Code Online (Sandbox Code Playgroud)
do_stuff()
不能被称为,而与
if (-1)
do_stuff();
Run Code Online (Sandbox Code Playgroud)
do_stuff()
必须被召唤; 因为它们是等价的,所以这不是法律定义NULL
.
但是标准说整数到指针的转换(反之亦然)是实现定义的,因此它可以定义-1到指针的转换,作为产生空指针的转换.在这种情况下
if ((void*)-1)
Run Code Online (Sandbox Code Playgroud)
会评价为假,一切都会好的.
那么别人怎么想呢?
我要求每个人特别记住中描述的"假设"规则2.1.2.3 Program execution
.它是巨大的,有点迂回,所以我不会在这里粘贴它,但它实质上说,一个实现只需要产生与标准描述的抽象机器所需的相同的可观察副作用.它表示,只要程序的可观察副作用不被它们改变,任何优化,转换或编译器想要对程序执行的任何其他操作都是完全合法的.
因此,如果您希望证明特定的定义NULL
不合法,您需要提出一个可以证明它的程序.任何一个像我一样公然打破标准中的其他条款,或者可以合法地检测编译器必须做的任何魔法来使奇怪的NULL定义工作.
Steve Jessop发现了一个程序检测方法的例子,NULL
它没有被定义为3.2.2.3中两种形式的空指针常量之一,它是将常量字符串化:
#define stringize_helper(x) #x
#define stringize(x) stringize_helper(x)
Run Code Online (Sandbox Code Playgroud)
使用这个宏,人们可以
puts(stringize(NULL));
Run Code Online (Sandbox Code Playgroud)
并"检测"NULL不会扩展到3.2.2.3中的一个表单.这足以使其他定义非法吗?我只是不知道.
谢谢!
为什么这段代码中的条件true
?
int main ( )
{
if ("")
cout << "hello"; // executes!
return 0;
}
Run Code Online (Sandbox Code Playgroud) 这可以被认为是这个问题的扩展(我只对C感兴趣,但添加C++来完成扩展)
6.3.2.3.3中的C11标准说:
值为0的整型常量表达式或此类表达式转换为类型
void *
称为空指针常量.
我个人对此的看法是0
并且(void *)0
表示空指针,其整数值实际上可能不是0,但是不包括0强制转换为任何其他类型.
但是,标准然后继续:
如果将空指针常量转换为指针类型,则生成的指针称为空指针,...
它包含(int *)0
为空指针,因为强制转换是一种显式转换(C11,6.3),它在转换方法下列出.
然而,令我惊讶的是以下短语
...或者这样的表达式转换为
void *
...
有了上面的语义,这句话似乎完全没用.问题是,这句话完全没用吗?如果没有,它有什么影响?因此,是否(int *)0
为空指针?
另一个可以帮助讨论的问题如下.被(long long)123
视为"123转换为long long
",或"123与类型long long
".换句话说,有没有转换(long long)123
?如果没有,则上面的第二个引用不包括(int *)0
为空指针.
如果你有像NSString*someString这样的对象,那么它们之间有什么区别(如果有的话)
if (!someString)
Run Code Online (Sandbox Code Playgroud)
VS
if (someString == nil)
Run Code Online (Sandbox Code Playgroud)
谢谢!
请考虑这样的堆分配的指针数组:
Thing** array = malloc(sizeof(Thing*) * array_length);
Run Code Online (Sandbox Code Playgroud)
如何设置其所有成员为NULL
?
我当然可以这样做:
for (int i = 0; i < array_length; i++) {
array[i] = NULL;
}
Run Code Online (Sandbox Code Playgroud)
但是我想知道是否有一个标准功能。
SO主要提到memset
,但是我不确定在此用例下是否可以保证在所有平台上都可以使用,因为据我所知,它是逐字节而不是逐元素地遍历数组。
同样更普遍的是,将任何类型的数组(T
可以是任意大小)中的所有值设置为某个特定值的标准方法是什么?
假设a
是一个指针,在为它分配内存之后,我想检查内存是否已成功分配,我已经看到了两种方法:
if(a != NULL)
if(a)
Run Code Online (Sandbox Code Playgroud)
第一个和第二个陈述有什么区别?
这个问题困扰了我一段时间.我从来没有看到过NULL的不同定义,它始终是
#define NULL ((void *) 0)
Run Code Online (Sandbox Code Playgroud)
是否有任何体系结构,其中NULL定义不同,如果是这样,为什么编译器不为我们声明这个?
在C中使用fgets读取文本文件直到EOF的正确方法是什么?现在我有了这个(简化):
char line[100 + 1];
while (fgets(line, sizeof(line), tsin) != NULL) { // tsin is FILE* input
... //doing stuff with line
}
Run Code Online (Sandbox Code Playgroud)
具体来说,我想知道是否应该有其他东西作为时间条件?从文本文件到"行"的解析是否必须在while条件下执行?
我最近遇到了GCC的错误,无法用一些东西来初始化{0}
.在该错误报告中,报告它的人说:
C标准库中的经典示例是mbstate_t:
mbstate_t state = { 0 }; /* correctly zero-initialized */
Run Code Online (Sandbox Code Playgroud)
与常见但不可移植的:
mbstate_t state;
memset(&state, 0, sizeof state);
Run Code Online (Sandbox Code Playgroud)
虽然我更喜欢并尝试使用{0}
初始化的东西为零,但我已经使用过,并且已经看到其他人使用,该memset
版本将某些东西设置为零.我过去没有遇到任何可移植性问题.
问题:memset
在这里使用真的不便携吗?如果是这样,在什么情况下会不便携?
c ×8
c++ ×2
if-statement ×2
arrays ×1
c++11 ×1
fgets ×1
iphone ×1
memset ×1
nul ×1
null ×1
null-pointer ×1
nullptr ×1
objective-c ×1
pointers ×1
standards ×1
string ×1
while-loop ×1