考虑以下计划:
int main()
{
int array[9];
const int (*p2)[9] = &array;
}
Run Code Online (Sandbox Code Playgroud)
它在C++中编译得很好(请参见此处的实时演示),但在C中编译失败.默认情况下,GCC会发出以下警告.(见此处的现场演示).
prog.c: In function 'main':
prog.c:4:26: warning: initialization from incompatible pointer type [enabled by default]
const int (*p2)[9] = &array;
Run Code Online (Sandbox Code Playgroud)
但如果我使用-pedantic-errors选项:
gcc -Os -s -Wall -std=c11 -pedantic-errors -o constptr constptr.c
Run Code Online (Sandbox Code Playgroud)
它给了我以下编译器错误
constptr.c:4:26: error: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]
Run Code Online (Sandbox Code Playgroud)
为什么它在C中编译失败而在C++中没有?C&C++标准对此有何看法?
如果我在数组声明语句中使用const限定符,它也可以在C中编译.那么,上面的程序中发生了什么?
考虑以下程序.这会给出任何编译错误吗?
#include <stdio.h>
int s=5;
int s;
int main(void)
{
printf("%d",s);
}
Run Code Online (Sandbox Code Playgroud)
乍一看似乎编译器会给出变量重定义错误,但程序根据C标准完全有效.(请参见http://ideone.com/Xyo5SY上的现场演示).
暂定定义是没有存储类说明符且没有初始化程序的任何外部数据声明.
C99 6.9.2/2
对于具有文件范围而没有初始化程序且没有存储类指定程序或存储类指定程序静态的对象的标识声明构成了一个暂定的定义.如果翻译单元包含一个或多个用于标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则该行为就像翻译单元包含该标识符的文件范围声明一样,其复合类型为翻译单元的结尾,初始化程序等于0.
我的问题是,允许暂定定义的理由是什么?在C中有没有用过这个?为什么C允许暂定?
为什么枚举值可以在用C语言定义枚举的块之外访问,而不是在C++中定义?
考虑以下C程序.
#include <stdio.h>
struct mystruct
{
enum {INT, FLOAT, STRING} type;
int integer;
float floating_point;
} tu;
/* Why is INT accessible here? */
int main()
{
tu.type = INT;
tu.integer = 100;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它在C中编译并运行良好.
但是在C++中,它在编译时失败了.
#include <iostream>
struct mystruct
{
enum {INT, FLOAT, STRING} type;
int integer;
float floating_point;
} tu;
/* Why is INT accessible here? */
int main()
{
tu.type = INT;
tu.integer = 100;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
[错误]未在此范围内声明'INT'
枚举和范围规则在C和C++中是不同的吗?
新标准具有与旧标准不同的未定义行为.例如,新的排序规则意味着现在定义了一些过去未定义的算术运算(出于诸如序列点之间的多次写入的原因).
那么,我们需要重新学习未定义的行为?
%n在这个问题上,我正在阅读C中的格式说明符.但是当我在不同的C++编译器上尝试以下程序时,它给了我不同的输出.
为什么?是什么原因?是否存在未定义或实现定义的行为?
#include<stdio.h>
int main()
{
int c = -1;
printf("geeks for %ngeeks ", &c);
printf("%d", c);
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
geeks for geeks 10
Run Code Online (Sandbox Code Playgroud)
geeks for geeks 10
Run Code Online (Sandbox Code Playgroud)
geeks -1
Run Code Online (Sandbox Code Playgroud)
Debug assertion failed ("'n' format specifier disabled",0)
Run Code Online (Sandbox Code Playgroud) 我写了下面的简单程序并在gcc编译器上编译
#include <stdio.h>
typedef int i;
void foo()
{
struct i {i i;} i;
i.i = 3;
printf("%i\n", i.i);
}
int main() { foo(); }
Run Code Online (Sandbox Code Playgroud)
它在C中编译并运行良好.(请参见此处的实时演示)但它在C++中编译失败.C++编译器提供以下错误消息.
prog.cc: In function 'void foo()':
prog.cc:5:17: error: field 'i' has incomplete type 'foo()::i'
struct i {i i;} i;
^
prog.cc:5:12: note: definition of 'struct foo()::i' is not complete until the closing brace
struct i {i i;} i;
Run Code Online (Sandbox Code Playgroud)
在这里查看现场演示
我无法在C&C++标准中找到关于此的规则.为什么它在C中编译好但在C++中编译不好?标准对此有何看法?我非常清楚C&C++是不同的语言,有不同的规则,但我很想知道确切的规则.
说我有以下程序
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int * i;
if ((i = malloc(sizeof(int) * 100)) == NULL) {
printf("EROOR: unable to allocate memory \n");
return -1;
}
/* memory is allocated successfully */
/* memory is not free'ed but program terminates */
// free(i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的程序调用malloc分配一些内存而不调用free取消分配它.程序终止而不取消分配内存.
Valgrind清楚地发现内存泄漏.
<snap>
==14209== HEAP SUMMARY:
==14209== in use at exit: 400 bytes in 1 blocks
==14209== total heap usage: 1 allocs, 0 frees, 400 bytes allocated …Run Code Online (Sandbox Code Playgroud) 请考虑以下示例:
#include <iostream>
#include <string>
struct ABC
{
std::string str;
unsigned int id ;/* = 0 : error: no matching constructor for initialization of 'ABC'*/
};
int main()
{
ABC abc{"hi", 0};
std::cout << abc.str << " " << abc.id << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在定义结构ABC而没有id clang 3.x和gcc 4.8.x的默认值时,编译代码没有问题.但是,在为"id"添加默认参数后,我得到了流动的错误消息:
13 : error: no matching constructor for initialization of 'ABC'
ABC abc{"hi", 0};
^ ~~~~~~~~~
4 : note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 …Run Code Online (Sandbox Code Playgroud) 我曾经在嵌入式系统的项目上工作过,我们重新安排了堆栈变量声明的顺序,以减少生成的可执行文件的大小.例如,如果我们有:
void func()
{
char c;
int i;
short s;
...
}
Run Code Online (Sandbox Code Playgroud)
我们会将此重新排序为:
void func()
{
int i;
short s;
char c;
...
}
Run Code Online (Sandbox Code Playgroud)
由于对齐问题,第一个导致使用12个字节的堆栈空间,第二个导致仅8个字节.
这是C编译器的标准行为,还是我们使用的编译器的缺点?
在我看来,编译器应该能够重新排序堆栈变量,以便在需要时支持更小的可执行文件大小.有人向我建议,C标准的某些方面可以防止这种情况,但我无法以任何方式找到信誉良好的来源.
作为一个额外的问题,这也适用于C++编译器吗?
编辑
如果答案是肯定的,那么C/C++编译器可以重新排列堆栈变量,你能给出一个肯定会这样做的编译器的例子吗?我想看看编译器文档或类似的东西支持这一点.
再次编辑
谢谢大家的帮助.对于文档,我能够找到的最好的东西是GCC(pdf)中的最佳堆栈槽分配,由Naveen Sharma和Sanjiv Kumar Gupta撰写,于2003年在海湾合作委员会峰会会议上提交.
这里讨论的项目是使用ADS编译器进行ARM开发.在该编译器的文档中提到,像我所示的排序声明可以提高性能以及堆栈大小,因为ARM-Thumb架构如何计算本地堆栈帧中的地址.该编译器没有自动重新排列本地人以利用这一点.这里链接的论文说,截至2003年,GCC也没有重新安排堆栈帧以改善ARM-Thumb处理器的参考局部性,但它暗示你可以.
我找不到任何明确表示这在GCC中实施过的东西,但我认为这篇论文可以证明你是正确的.再次感谢.
考虑以下程序:
#include <iostream>
struct Test
{
int a;
Test() : a(3)
{ }
Test(const Test& t...)
{
std::cout<<"Copy constructor called\n";
a=t.a;
}
int get_a()
{
return a;
}
~Test()
{
std::cout<<"Destructor is called\n";
}
};
int main()
{
Test t;
Test* t1=new Test(t);
std::cout<<t.get_a()<<'\n';
std::cout<<t1->get_a()<<'\n';
delete t1;
}
Run Code Online (Sandbox Code Playgroud)
仔细观察复制构造函数参数中的三个点我尝试这个程序时真的很惊讶.有什么用?这是什么意思?
语言规范对此有何看法?
我知道三个点用于表示变量函数(如等)中的变长参数printf()以及scanf()C99引入的可变参数宏.在C++中,如果我没有错,它们将用于可变参数模板.
这段代码是否形成良好?这个可变参数构造函数是否可以使用任意数量的参数?
它在g ++ 4.8.1和MSVS 2010上编译并运行良好.