为了使我所说的更清楚,这是一个例子.
有这个课程:
@interface Person : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
- (void)sayHi;
@end
Run Code Online (Sandbox Code Playgroud)
有了这个实现:
@implementation Person
@synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)sayHi {
NSLog(@"Hello");
NSLog(@"My name is %@.", name);
}
@end
Run Code Online (Sandbox Code Playgroud)
在程序的某个地方,我这样做:
Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike"; // shouldn't I get an error here?
[person sayHi]; // and here
[person release]; // and …Run Code Online (Sandbox Code Playgroud) 在一些遗留代码中,我遇到了以下空指针检查。
if( myPtr > 0 ) {
...
}
Run Code Online (Sandbox Code Playgroud)
通过此 if 检查检查空指针是否存在任何技术风险?
在C中,引用空指针是未定义行为,但是空指针值具有位表示,在某些体系结构中它使其指向有效地址(例如地址0).为了清楚起见,
我们将此地址称为空指针地址.
假设我想在C中编写一个软件,在一个无限制访问内存的环境中.假设我想在空指针地址处写一些数据:我将如何以符合标准的方式实现这一点?
示例案例(IA32e):
#include <stdint.h>
int main()
{
uintptr_t zero = 0;
char* p = (char*)zero;
return *p;
}
Run Code Online (Sandbox Code Playgroud)
当使用带有-O3的 gcc与IA32e 编译时,此代码将转换为
movzx eax, BYTE PTR [0]
ud2
Run Code Online (Sandbox Code Playgroud)
由于UB(0是空指针的位表示).
由于C接近低级编程,我相信必须有一种方法来访问空指针地址并避免UB.
为了清楚
起见,我问的是标准对此有何看法,而不是如何以实现定义的方式实现这一点.
我知道后者的答案.
gcc -std=c23最新的 gcc 13.x (trunk) 给出了此代码的编译器错误 ( ):
int* p = false;\nRun Code Online (Sandbox Code Playgroud)\n\n\n错误:
\nint *使用类型“ ”初始化类型“_Bool”时出现类型不兼容
这怎么可能是正确的呢?
\nC23 6.2.5 \xc2\xa78-9(类型 - 整数类型的定义):
\n\n\n\n
bool与标准有符号整数类型相对应的类型和无符号整数类型是标准无符号整数类型。标准有符号整数类型和标准无符号整数类型统称为标准整数类型;
\n
C23 6.6 \xc2\xa78 (常量表达式 - 整型常量表达式的定义):
\n\n\n整数常量表达式应具有整数类型...
\n
C23 6.3.2.3(指针-空指针常量的定义)
\n\n\n值为 0 的整型常量表达式,此类表达式转换为 类型
\nvoid *,或预定义常量nullptr称为空指针常量
C23 6.5.16.1(简单分配):
\n\n约束
\n/--/ …
我正在学习C++,并且我开始知道指针如果保持未初始化可能指向内存中的随机位置并产生内存可能被其他程序使用的问题.
现在,如果是这种情况,我们就不应该在代码的任何部分使用这一行:
int* ptr;
Run Code Online (Sandbox Code Playgroud)
相反,我们应该有类似的东西
int* ptr = NULL; //Is this going to avoid the problem
Run Code Online (Sandbox Code Playgroud)
请建议,因为我int* ptr;在很多书中看过第一行(),所以我对此表示怀疑.如果可能的话也举一些例子.
我知道delete空指针是一个无操作:
在任一替代方案中,如果delete的操作数的值是空指针,则操作无效.
(C++标准5.3.5 [expr.delete] p2)
并且删除void*指针是未定义的行为,因为无法调用析构函数,因为没有类型的对象void:
在第一个alternative(
delete object)中,delete的操作数的值应该是指向非数组对象的指针或指向表示这种对象的基类的子对象的指针.如果不是,则行为未定义.
(C++标准5.3.5 [expr.delete] p2)
现在,通常我认为列出的东西首先列出了后面列出的东西,但是空void*指针如下呢?
void* p = 0;
delete p; // UB or well-defined?
Run Code Online (Sandbox Code Playgroud) c++ void-pointers null-pointer undefined-behavior language-lawyer
我不明白为什么下面的代码编译?
int main()
{
//int a = nullptr; // Doesn't Compile
//char b = nullptr; // Doesn't Compile
bool c = nullptr; // Compiles
return 0;
}
Run Code Online (Sandbox Code Playgroud)
而评论部分没有.
这两个bool和nullptr是关键字,那么什么是关于其他数据类型的独特之处?
我遇到了一段代码片段,对我来说应该会因为分段错误而崩溃,但它可以毫无障碍地工作.有问题的代码加上相关的数据结构如下(在上面找到相关的评论):
typedef struct {
double length;
unsigned char nPlaced;
unsigned char path[0];
}
RouteDefinition* Alloc_RouteDefinition()
{
// NB: The +nBags*sizeof.. trick "expands" the path[0] array in RouteDefinition
// to the path[nBags] array
RouteDefinition *def = NULL;
return (RouteDefinition*) malloc(sizeof(RouteDefinition) + nBags * sizeof(def->path[0]));
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做?我收集了的sizeof的字符*将解决对给定的体系结构指针的大小,但它不应该和好如初,同时取消引用NULL终场?
我知道三元运算符有一些令人惊讶的限制,但我有点困惑,这无法为我编译:
void foo(bool b)
{
int* ptr = ((b) ? NULL : NULL);
}
Run Code Online (Sandbox Code Playgroud)
显然,这是显示问题所需的最低限度.错误是:
[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'
Run Code Online (Sandbox Code Playgroud)
编译器是不到100%符合Embarcadero C++ Builder 2010的,因此编译器错误远非不可能......
注意:修改Parens以避免混淆我的意图.
注2:我对自己如何首先得到这个结构感到有些困惑,所以这是我的借口:我在一行上得到了一些编译错误a = b? c : d,其中b,c和d都是复杂的表达式.为了缩小范围,我用s 代替c,以检查是否是罪魁祸首.在这一点上,一切都在手推车里下地狱.dNULLb
c++ conditional-operator null-pointer c++builder-2010 constant-expression
我很想知道它是如何nullptr工作的。标准 N4659 和 N4849 说:
std::nullptr_t;sizeof(std::nullptr_t) == sizeof(void*);bool为false;(void*)0,但不能向后转换;所以它基本上是一个与 具有相同含义的常量(void*)0,但它具有不同的类型。我std::nullptr_t在我的设备上找到了实现,如下所示。
#ifdef _LIBCPP_HAS_NO_NULLPTR
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS nullptr_t
{
void* __lx;
struct __nat {int __for_bool_;};
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
operator _Tp* () const {return 0;}
template <class _Tp, class …Run Code Online (Sandbox Code Playgroud) null-pointer ×10
c++ ×6
c ×3
pointers ×2
c++11 ×1
c++17 ×1
c23 ×1
comparison ×1
dereference ×1
gcc ×1
iphone ×1
null ×1
null-check ×1
nullptr ×1
objective-c ×1
sizeof ×1