在C99中,我包含了stdint.h,它给了我UINT32_MAX和uint32_t.但是,在C++中,UINT32_MAX被定义出来.我可以在包含stdint.h之前定义__STDC_LIMIT_MACROS,但是如果有人在已经包含stdint.h之后包含我的头文件,则这不起作用.
那么在C++中,找出uint32_t中可表示的最大值的标准方法是什么?
从我系统的手册页:
void*memmove(void*dst,const void*src,size_t len);
描述
memmove()函数将字符串src中的len个字节复制到字符串dst.
两个字符串可能重叠 ; 副本总是以非破坏性的
方式完成.
从C99标准:
6.5.8.5比较两个指针时,结果取决于指向的对象的地址空间中的相对位置.如果指向对象或不完整类型的两个指针都指向同一个对象,或者两个指针都指向同一个数组对象的最后一个元素,则它们相等.如果指向的对象是同一聚合对象的成员,则指向稍后声明的结构成员的指针比指向结构中先前声明的成员的指针大,指向具有较大下标值的数组元素的指针比指向同一数组的元素的指针大.具有较低的下标值.指向同一个union对象的成员的所有指针都比较相等.如果表达
P指向数组对象的元素,表达式Q指向同一数组对象的最后一个元素,指针表达式Q+1比较大于P.在所有其他情况下,行为 未定义.
重点是我的.
的参数dst和src可被转化为指针char以便减轻严格别名的问题,但有可能以比较两个指针可以指向内部的不同的块,以便做以正确的顺序的拷贝的情况下,它们指向相同的块内?
显而易见的解决方案是if (src < dst),但未定义如果src和dst指向不同的块."未定义"意味着您甚至不应该假设条件返回0或1(这在标准词汇表中称为"未指定").
另一种选择是if ((uintptr_t)src < (uintptr_t)dst),至少是未指定的,但我不确定标准是否保证何时src < dst定义,它等同于(uintptr_t)src < (uintptr_t)dst).指针比较是从指针算法定义的.例如,当我在添加时阅读第6.5.6节时,在我看来,指针算法可以与uintptr_t算术相反的方向,即兼容的编译器可能具有,当p类型为char*:
((uintptr_t)p)+1==((uintptr_t)(p-1)
Run Code Online (Sandbox Code Playgroud)
这只是一个例子.一般来说,将指针转换为整数时,似乎可以保证很少.
这是一个纯粹的学术问题,因为memmove它与编译器一起提供.在实践中,编译器作者可以简单地将未定义的指针比较提升为未指定的行为,或者使用相关的编译指示强制其编译器memmove正确编译它们.例如,此实现具有以下代码段:
if ((uintptr_t)dst < (uintptr_t)src) {
/*
* As author/maintainer of libc, take advantage …Run Code Online (Sandbox Code Playgroud) 我正在Eclipse中开展一个小型C项目; 我刚刚从Ubuntu软件中心安装了Eclipse并添加了C/C++语言支持.我可以很好地构建,运行和调试简单的C程序.
但是我现在正在使用一些C99功能,而且Eclipse抱怨说"'''循环初始声明'只允许在C99模式下使用".
我以为你在makefile中为GCC设置了C99模式,但是makefile是由Eclipse自动生成的,所以我所做的任何更改都会被覆盖,但是我没有看到任何地方将GCC编译器选项放在Eclipse的首选项中,也没有项目属性窗口.
那么我在哪里定义C99模式?
考虑由两个文件组成的C程序,
在f1.c:
int x;
Run Code Online (Sandbox Code Playgroud)
f2.c:
int x=2;
Run Code Online (Sandbox Code Playgroud)
我对C99标准第6.9.2段的解读是该程序应该被拒绝.在我对6.9.2的解释中,变量x是暂定的f1.c,但是这个暂定的定义在翻译单元的末尾变成了一个实际的定义,并且(在我看来),应该表现得好像f1.c包含了定义int x=0;.
对于所有编译器(以及重要的是,链接器)我能够尝试,这不是发生的事情.我试过的所有编译平台都链接了上面两个文件,两个文件中的值x都是2.
我怀疑这是偶然发生的,或者只是作为标准要求提供的"简单"功能.如果你考虑一下,这意味着链接器中对那些没有初始化器的全局变量有特殊支持,而不是那些显式初始化为零的全局变量.有人告诉我,无论如何编译Fortran可能都需要链接器功能.那将是一个合理的解释.
有什么想法吗?对标准的其他解释?文件f1.c和f2.c拒绝链接在一起的平台名称?
注意:这很重要,因为问题出现在静态分析的上下文中.如果这两个文件可能拒绝在某个平台上链接,分析器应该抱怨,但是如果每个编译平台都接受它,那么就没有理由对它进行警告.
显然,以下函数原型在C99和C11中有效:
void foo(int a[const *]);
void bar(int a[static volatile 10]);
Run Code Online (Sandbox Code Playgroud)
什么是那些奇怪的符号下标为目的*,static和CV预选赛?
它们有助于区分静态类型数组和可变长度数组吗?或者他们只是语法糖?
我在这里看到了这个,我不知道这意味着什么:
&(int) { 1 }
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪,因为它似乎是无效的语法.它正在构建一个块范围(?),中间有一个随机1(没有分号)并取地址.对我来说没有多大意义.你们能开导我吗?
尝试用C++ 11,所以它编译:
auto a = &(int) { 1 };
Run Code Online (Sandbox Code Playgroud)
但我不知道如何处理变量.
您认为哪种C宏最有用?我找到了以下一个,用于在C中进行矢量运算:
#define v3_op_v3(x, op, y, z) {z[0]=x[0] op y[0]; \
z[1]=x[1] op y[1]; \
z[2]=x[2] op y[2];}
Run Code Online (Sandbox Code Playgroud)
它的工作方式如下:
v3_op_v3(vectorA, +, vectorB, vectorC);
v3_op_v3(vectorE, *, vectorF, vectorJ);
...
Run Code Online (Sandbox Code Playgroud) 我已经包含了标题netdb.h,包含在哪里getaddrinfo,但是gcc发出了这个警告:
warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
gcc -m32 -static -s -O2 -std=c99 -D_POSIX_C_SOURCE=200112L myprogram.c
Run Code Online (Sandbox Code Playgroud)
如何静态编译丢失的文件?
可能的解决方案:
可能是glibc安装缺少静态编译所需的相应目标文件.如果是这种情况,请创建相应的目标文件并在编译时链接它.
尝试EGLIBC而不是glibc.
我成功地用dietlibc编译了我的程序,它编译时没有任何错误加上得到的二进制文件比glibc制作的要小得多.
这听起来有点像面试问题,但实际上是一个实际问题.
我正在使用嵌入式平台,并且仅提供这些功能的等价物:
此外,printf()实现(和签名)很可能在不久的将来发生变化,因此对它的调用必须驻留在一个单独的模块中,以便以后易于迁移.
鉴于这些,我可以在一些函数或宏中包装日志记录调用吗?目标是我的源代码THAT_MACRO("Number of bunnies: %d", numBunnies);在一千个地方调用,但是只能在一个地方看到对上述函数的调用.
编译器:arm-gcc -std = c99
是否所有指针都是从指向结构类型的指针派生的问题都不容易回答.我发现这是一个重要问题,主要有以下两个原因.
A.缺少指向"任何"不完整或对象类型的指针,对方便的函数接口施加了限制,例如:
int allocate(ANY_TYPE **p,
size_t s);
int main(void)
{
int *p;
int r = allocate(&p, sizeof *p);
}
Run Code Online (Sandbox Code Playgroud)
[ 完整代码示例 ]
指向"任何"不完整或对象类型的现有指针明确描述为:
C99/ C11 §6.3.2.3 p1:
指向void的指针可以转换为指向任何不完整或对象类型的指针.[...]
从指向"任何"不完整或对象类型的现有指针派生的指针,指向void的指针,严格地是指向void的指针,并且不需要使用从指向"任何"不完整的指针派生的指针进行转换或对象类型.
B.程序员根据他们对特定实现的经验,使用基于不需要的假设的约定,有意识地或不知不觉地与指针的泛化相关,这种情况并不少见.假设,例如可转换,可表示为整数或共享公共属性:对象大小,表示或对齐.
根据C99 §6.2.5 p27/ C11 §6.2.5 p28:
[...]所有指向结构类型的指针应具有相同的表示和对齐要求.[...]
其次是C99 TC3 Footnote 39/ C11 Footnote 48:
相同的表示和对齐要求意味着可互换性作为函数的参数,函数的返回值和联合的成员.
虽然标准没有说:"指向结构类型的指针"并且选择了以下单词:"所有指向结构类型的指针",但它没有明确指定它是否适用于这种指针的递归推导.在标准中提到指针的特殊属性的其他情况下,它没有明确指定或提及递归指针派生,这意味着"类型派生"适用,或者它没有 - 但它没有明确提到.
虽然在引用类型时使用"所有指针"的措辞只使用两次,(对于结构和联合类型),而不是更明确的措辞:在整个标准中使用的"指针",我们不能总结它是否适用于这种指针的递归推导.