如何在大多数平台上使用C99标准类型以获得最大的可移植性和效率?
首先,这是我理解的,并认为这个问题是正确的. 对单个变量(例如计数器或for循环索引)使用快速数据类型.例如: #define LOOP_COUNT (100U) uint_fast8_t index; for(index = 0; index = 16位平台中最快,但在int int中的最低限度为16位,但在uint8_t,则在编译器添加AND 0xFF指令以检查每个增量的溢出时,它将在> 8位平台上较慢(我的ARM7编译器即使在全速优化方面都可以做到这一点). size_t也不是一个选择,因为它可能大于本机整数大小. 如果期望8位溢出,则不会发生这种情况.程序员应手动检查溢出(因为他/她应该恕我直言),如果忘记
2 2023-05-23
编程技术问答社区
用C语言中的预取和缓存优化对数组的线性访问
披露:我在programers.stack上尝试了类似的问题,但是这个地方远不及活动堆栈. 介绍 我倾向于使用许多大图像.它们还以多个序列的序列来进行,必须经过处理并反复播放.有时我会使用GPU,有时是CPU,有时两者兼而有之.大多数访问模式本质上是线性的(来回),这使我思考了有关数组的更多基本内容,以及如何在给定硬件上进行最大的记忆带宽来编写代码(允许计算不阻止读/写)) . 测试规格 我已经在2011 MacBookAir4,2(I5-2557M)上使用4GB RAM和SSD完成了此操作.除了iterm2. ,在测试期间没有其他运行 GCC 5.2.0(Homebrew)带有标志:-pedantic -std=c99 -Wall -Werror -Wextra -Wno-unused -O0带有附加的包含和库标志以及框架标志,以便使用我倾向于使用的GLFW计时器.我本来可以做到的,没关系.当然,所有64位. 我尝试了使用可选的-fprefetch-loop
0 2023-05-23
编程技术问答社区
在C99中,一个指定的初始化器可以合法地引用它所初始化的变量吗?
gcc和clang均允许指定的初始化器参考结构或数组的初始化,但是该法律和定义良好的行为? 以下代码示例编译和运行GCC和Clang和Outputs { .a = 3, .b = 6, }在两种情况下: #include typedef struct { int a; int b; } foo; int main() { foo bar = { .a = 3, .b = bar.a + 3, }; printf("{ .a = %d, .b = %d, }\n", bar.a, bar.b); return 0; } gcc生成以下输出(编译器Explorer Explorer链接)对于此示例是安全的: mov dword ptr [rbp - 4], 0 mov dword ptr [rbp - 16], 3 mov eax, dwor
2 2023-05-23
编程技术问答社区
C99中的通过引用传递
我只是阅读 this : 在C ++(和C99)中,我们可以通过 参考,提供相同的参考 作为指针的性能. 所以我尝试了这个简单的代码: #include void blabla(int& x){ x = 5; } int main(){ int y = 3; printf("y = %d\n", y); blabla(y); printf("y = %d\n", y); } 输出为: gcc test.c -o test -std=c99 test.c:3:16: error: expected ';', ',' or ')' before '&' token test.c: In function 'main': test.c:10:2: warning: implicit declaration of function 'blabla' 现在我很困惑.通过C99的支持是否确实支持?
0 2023-05-20
编程技术问答社区
C语言中参数数组类型中的 "静态 "是什么意思?
我看到以下几乎没有复杂的功能定义. void foo(double A[static 10]) { double B[10]; } 它是有效的C&C ++代码吗?是C99或C ++标准引入的新语法吗?它的目的是什么?我什么时候应该使用它?这个需要什么? 解决方案 此C99表示法,void foo(double A[static 10]),意味着该函数可以假定A指向10个有效参数(从*A到A[9]).该符号使程序更具信息性,帮助编译器既优化了针对函数foo生成的代码,又可以在每个呼叫网站上正确调用它. 在引入符号的C99标准中,该条款为6.7.5.2和6.7.5.3:7. . "…如果关键字静态也出现在数组类型派生的[和]中,那么对于每个调用函数,相应的实际参数的值应提供至少对数组的第一个元素的访问权限大小表达式指定的元素 指定的元素 一种常见用途是f(int p[static 1]),它或多或少等同于参考(与指针相对)的概念. Clang
0 2023-05-19
编程技术问答社区
C函数的声明不完整
我可以在没有错误的情况下构建此示例: void dummy() {} int main(void) { dummy(1, 2, 3); dummy(120, 144); } 拆卸表明该功能确实称为两次: main: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $15, %edx movl $14, %esi movl $12, %edi movl $0, %eax call foo movl $300, %esi
0 2023-05-19
编程技术问答社区
是否有一个GCC关键字来允许结构记录?
我知道为什么GCC不默认地重新订购结构的成员,但是我很少编写依赖结构顺序的代码,所以我是否可以将结构标记为自动重新排序? 解决方案 以前的GCC版本具有 选项允许在-fwhole-program + -combine模式下重新排序结构. -fipa-struct-reorg 执行结构重组优化,以更改类似C的结构布局,以便更好地利用空间位置.这种转换对包含结构阵列的程序具有影响力.有两种汇编模式可用:基于配置文件(使用-fprofile-generate启用)或静态(使用内置启发式方法).要求-fipa-type-escape提供此转换的安全性.它仅在整个程序模式下工作,因此需要启用-fwhole-program和-combine.这种转换考虑的结构不受影响(参见--param struct-reorg-cold-struct-ratio=value). 由于GCC 4.8.x自发行注释 已删除了struct reorg和matrix reorg优化(命令行选项
4 2023-05-16
编程技术问答社区
在C语言中使用GCC-多参数函数进行函数重载
在上一个问题中,当每个函数仅采用一个参数时,我找到了一种在C99中超负荷功能的方法.请参阅以下答案:使用GCC中的C函数过载 - 使用GCC-编译器警告有关详细信息 . 现在,我已经找到了一种使用单个参数函数来完成的方法,我想知道如何为采用多个参数的函数做到这一点.我认为这将与__VA_ARGS__有关,并且使用...,但我似乎找不到任何有效的东西甚至想编译的东西. 这将适用于获得2个参数的打印: #define print(x, y) \ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int) && \ __builtin_types_compatible_p(typeof(y), int), print_int,
0 2023-05-15
编程技术问答社区
C99不支持函数重载,有什么原因吗?
显然(至少根据gcc -std=c99)C99不支持函数过载.不支持C中某些新功能的原因通常是向后兼容,但是在这种情况下,我无法想到一种函数超载会破坏向后兼容性的情况.不包括此基本功能的原因是什么? 解决方案 要了解为什么您不太可能在C中看到过载,这可能有助于更好地了解C ++处理过载. 编译代码后,但是在准备运行之前,必须链接中间对象代码.这将编译功能和其他对象的粗糙数据库转换为准备加载/运行二进制文件的一个.此额外的步骤很重要,因为它是可用于编译程序的模块化的主要机制.此步骤使您可以从现有库中获取代码并将其与您自己的应用程序逻辑混合. 在此阶段,对象代码可以用任何语言编写,并具有任何功能组合.为了实现这一目标,有必要拥有某种惯例,以便链接器能够在另一个对象引用该对象时选择正确的对象.如果您用汇编语言进行编码,则当您定义标签时,该标签将完全使用,因为它假定您知道自己在做什么. 在C中,函数成为链接器的符号名称,因此,当您编写 时 int main(int
6 2023-05-15
编程技术问答社区
GCC。允许C99中的重载函数
我在C99中编写代码,并通过GCC编译.我想出于风格原因使用功能过载(否则我必须自己做名字). 我读过是否有C99的原因不支持功能过载?但是,我仍然想知道是否可以在GCC中启用它. 此时您能帮我吗? 解决方案 否,C99中没有功能过载,甚至在愚蠢的GCC扩展中也没有. C11添加了_Generic,但即使那样,您仍然必须自己命名自己. void foo_int(int x); void foo_double(double x); #define foo(arg) _Generic((arg), int: foo_int, double: foo_double)(arg) 无论好坏,好吧.是c. 其他解决方案 在C宏中可以部分替换其他语言的功能过载.正如Cat plus在她的答案中指示的那样,C11具有额外的构造_Generic程序类型通用宏. 使用C99,您已经有可能编程宏在某种意义上是通用类型的宏. p99 具有减轻此功能的设施宏具有不同数
0 2023-05-15
编程技术问答社区
在C语言中使用GCC-编译器警告的函数重载
我试图在 c 中实现功能过载,我非常接近.我正在使用C99,因此我无法使用C11中引入的_Generic关键字.我已经开发了一些工作代码,但是当我编译时,我会收到一些警告. 工作示例: #include #define print(x) \ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), int ), print_int(x) , \ __builtin_choose_expr(__builtin_types_compatible_p(typeof(x), char[]), print_string(x), \ (void)0)) void print_int(int i) { printf("int: %d\n", i
0 2023-05-15
编程技术问答社区
在数组中使用restrict?
有没有办法告诉C99编译器,我将要使用MyArray [index]访问数组的唯一方法? 说这样的话: int heavy_calcualtions(float* restrict range1, float* restrict range2) { float __I promise I won't alias this__ tmpvalues[1000] = {0}; .... heavy calculations using range1, range2 and tmpvalues; .... } 通过使用限制,我保证我不会别名range1和range2,但是我该如何为在功能中声明的数组做同样的事情? 解决方案 尽管Jeff的答案是正确的,即,您可以随时将指针定为分配的数组,但事实是编译器在编译时知道 TMPVALUES不会使TMPVALUES变得不明服因为该变量被声明为实际数组,而不是指针.别名阵列的唯一机会是宣布指向指针,因此,
2 2023-05-12
编程技术问答社区
intXX_t和int_fastXX_t之间的区别是什么?
我最近发现了标准最快类型的存在,主要是 int_fast32_t 和 我总是被告知,为了在主流体系结构上进行正常使用,应该更好地使用经典 int & long ,它应该始终适合处理器默认阅读能力,因此避免使用无用的数字转换. 在C99标准中,它在§7.18.1.3p2中说: " typedef名称int_fastn_t指定宽度至少为n的最快签名的整数类型.typedef名称uint_fastn_t指定宽度至少为n的最快的无符号整数类型." > ,在§7.18.1.3p1中也有一个报价: "指定的类型不能保证所有目的最快;如果实现没有明确的理由选择一种类型而不是另一种类型,则只需选择一些满足签名和宽度要求的整数类型." ." . 我不清楚最快的真正含义.我不明白什么时候应该使用这种类型,什么时候不应该使用. 我对此有所搜索,发现一些 open source 项目已将其一些功能更改为其中,但并非全部.他们并没有真正解释为什么他们更改了部分, 是其代码的一部
2 2023-05-12
编程技术问答社区
当p和q指向同一个对象时,"*p = ++(*q) "是否未定义?
阅读了有关序列点后,我了解到i = ++i是未定义的. 那么此代码如何: int i; int *p = &i; int *q = &i; *p = ++(*q); // that should also be undefined right? 假设P和Q的初始化是否取决于某些(复杂的)条件. 它们可能像上述情况一样指向相同的对象. 会发生什么?如果不确定,我们可以使用哪些工具来检测? 编辑:如果不应该指向同一对象,我们可以使用C99限制吗? 这是什么意思? 解决方案 是的,这是未定义的行为 - 您对对象进行了两个修改,而它们之间没有序列.不幸的是,自动检查此功能非常困难 - 我能想到的最好的是在此之前添加assert(p != q),这至少会产生干净的运行时故障,而不是更糟.在一般情况下,在编译时检查此内容是不可确定的. 其他解决方案 最佳的工具不检测到,但首先要避免这种方法是使用良好的编程实践.避免副作用,并且每次分配不超过
6 2023-05-12
编程技术问答社区
C, Open MPI:调用MPI_Finalize()时出现分段故障。Segfault并不总是发生,特别是在进程数量较少的情况下
我正在编写一个简单的代码,以学习如何定义mpi_datatype并将其与mpi_gatherv结合使用.我想确保我可以在一个过程上结合变量长度,动态分配的结构化数据数组,这似乎工作正常,直到我致电mpi_finalize().我已经确认这是通过使用打印语句和Eclipse PTP调试器(后端是GDB-MI)开始表现出来的问题.我的主要问题是,我如何摆脱分割错误? 每次运行代码时,不会发生SEGFAULT.例如,它没有发生2或3个过程,但是当我使用大约4个或更多过程运行时,往往会定期发生. 另外,当我使用Valgrind运行此代码时,不会发生分割故障.但是,我确实会从Valgrind那里收到错误消息,尽管即使使用大量目标抑制,我也很难理解输出我很难理解.我还担心,如果我使用更多抑制作用,我会沉默有用的错误消息. 我使用这些标志对普通代码进行编译,因此我在两种情况下都使用C99标准: -ansi -pedantic -wall -O2 -March =巴塞罗那-fomit
0 2023-05-11
编程技术问答社区
在OpenCL中传递一个函数作为参数
是否可以将功能指针传递给OpenCL 1.2中的内核?我知道可以在C中完成,但是我不知道该如何在Opencl的c. 中做到这一点. 编辑: 我想做同样的事情与这篇文章中描述的事情:您如何将函数作为C? 以前,我已经使用内联函数从内核调用它们,但是我希望该函数是一个参数,而不是硬编码. 解决方案 简短: opencl's c!= c,将其视为大多数看起来像C的句法帮助,但它不能涵盖所有语言细节,并将其扩展到某个时刻,并且不提供该语言(请参阅第233页的规格,6.9 a:因此,您无法做到. 详细: 传递函数指针在C中是一种构造代码以优化逻辑的方式.另一方面,内核并不是构造事物的重点,而是一个要优化您编码以最大可能效率的每行的要点.最后,所有内容都将组合到每个线程都将执行的单个程序中,并且您调用的每个函数都会被内衬(您没有CPU上的呼叫堆栈). 因此,在这种情况下,您想要的是重新考虑要按C中实现的程序逻辑,以便为一个或多个内核调用优化它,以消除功能指针方法
2 2023-05-09
编程技术问答社区
OpenCL中不允许变长数组声明--为什么?
我想在opencl内核中创建一个本地数组,该数组的大小取决于内核的参数.似乎不允许 - 至少使用AMD应用程序. 您的经历与众不同吗?也许只是应用程序?还是这里有一些理由? 编辑:我现在建议在CPU侧代码中也允许可变长度阵列,这是C标准委员会不幸的呼吁;但是问题是. 解决方案 您可以动态分配本地块的大小.您需要将其作为内核的参数,并在调用Clsetkernelarg时定义其大小. 定义示例: __kernel void kernelName(__local float* myLocalFloats, ...) 主机代码: clSetKernelArg(kernel, 0, myLocalFloatCount * sizeof(float), NULL); //
4 2023-05-09
编程技术问答社区
不在Objective-C中使用_Bool的原因?
自C99以来,C现在具有适当的布尔类型,_Bool. Objective-C作为C的严格超集C,继承了这一点,但是当它在1980年代创建时,没有C Boolean类型,因此Objective-C定义为BOOL为signed char. 所有可可的使用BOOL,以及我所看到的所有非邻近/苹果可可代码也是如此.显然,为了与现有协议的兼容性(例如,-applicationShouldTerminateAfterLastWindowClosed:来自NSApplicationDelegate),如果没有其他原因避免警告. 出于清洁/可读性目的,stdbool.h将bool定义为_Bool的同义词,因此我们中那些不需要不必要的下强调的人可以使用它. 其他三个有用的说明: @encode(_Bool)评估"B". (@encode(BOOL)评估"c",signed char.) sizeof(_Bool)评估1,这是从C99的定义来看,_Bool _Bool持有其两个可能
0 2023-05-05
编程技术问答社区
仿真器/生成的开关语句范围为c
在C(99?)或目标C开关语句中有支持范围案例的黑客攻击吗? 我知道这不支持写这样的东西: switch(x) case 1: case 2..10: case 11: ,但我认为应该有一种用#Define宏来生成代码的方法.当然 我可以为案例列表定义一个宏,但我希望以一种更优雅的方式 Caserange(X,X+10),将生成: case x case x+1 case x+2 甚至可能吗? 解决方案 GCC具有扩展到C语言/a>允许与您的第一个示例类似的内容,但是除此之外,如果有一种便携式/ANSI的方法,它将已经完成.我不相信有一个. 其他解决方案 使用宏进行此操作即将接近或不可能.存在编译器扩展名,但它们是特定于编译器的,而不是跨平台/标准的.没有标准的方法可以做到,如果/否则/其他链. 其他解决方案 在现代C(C99,具有可变长度宏)中,可以使用宏进行.但是,您可能不想自己编写这个编码. p99 为此提供了一个工具箱
4 2023-05-05
编程技术问答社区
函数的隐式声明-C99
我当前正在使用Xcode 4,在我的.pch文件中,我有此宏: #define localize(s) NSLocalizedString((s), nil). 当我尝试在某些.m文件中使用此宏时,我会收到此警告:Implicit declaration of function 'localize' is invalid in C99. 此代码毫无问题地编译,但是我该如何解决此问题,以免警告? 解决方案 当我用DLOG对NSLOG进行全局替换时,我遇到了这个问题.我愚蠢地包括了 #define DLog(...) NSLog(... 语句,所以我结束了 #define DLog(...) DLog(... 引起警告和链接器错误. 其他解决方案 隐式函数声明是编译器首次将用作函数调用的编译器(而不是首先看到原型或功能定义的函数). 显然您使用的代码localize(foo),但宏定义不可见.可能的原因:您忘记了#include包含local
4 2023-05-04
编程技术问答社区