在C中模拟布尔值可以这样做:
int success;
success = (errors == 0 && count > 0);
if(success)
...
Run Code Online (Sandbox Code Playgroud)
随着stdbool.h包括以下可以做:
bool success;
success = (errors == 0 && count > 0) ? true : false;
if(success)
...
Run Code Online (Sandbox Code Playgroud)
根据我的理解,逻辑和比较运算符应返回1或0.此外,stdbool.h应定义常量以便true == 1和false == 0.
因此,以下应该工作:
bool success;
success = (errors == 0 && count > 0);
if(success)
...
Run Code Online (Sandbox Code Playgroud)
它确实适用于我测试过的编译器.但是假设它是可移植代码是否安全?(假设stdbool.h存在)
因为bool是内部类型,C++编译器的情况是否不同?
考虑以下代码:
var arr = [111, 222, 333];
for(var i in arr) {
if(i === 1) {
// Never executed
}
}
Run Code Online (Sandbox Code Playgroud)
它会失败,因为typeof i === 'string'.
这有什么办法吗?我可以显式转换i为整数,但这样做似乎使用simpler for in而不是regular for-loop来破坏目的.
编辑:
我知道==比较使用,但这不是一个选择.
编译器通常在结构上插入尾部填充以在数组中使用它们时满足对齐限制:
// Size 4, alignment 2
struct A {
uint16_t x;
uint8_t y;
// Padding 1 byte
};
// Size 6, alignment 2
struct B {
struct A xy;
uint8_t z;
// Padding 1 byte
};
Run Code Online (Sandbox Code Playgroud)
现在考虑使用内部结构组合这些:
struct AB {
struct {
uint16_t x;
uint8_t y;
} xy;
uint8_t z;
};
Run Code Online (Sandbox Code Playgroud)
以下可以适合4个字节,同时不会破坏对齐限制.此外,内部结构xy没有可以在别处使用的类型,因此不需要使用尾随填充.
缺点是该成员xy不兼容struct A,但没有理由说它们应该是不同的类型定义.
是否允许编译器进行此大小优化?
或者,换句话说,标准是否要求具有相同成员的2个结构总是导致相同的布局?
以下代码可能存在未定义的行为:
uint64_t arr[1]; // Uninitialized
if(arr[0] == 0) {
Run Code Online (Sandbox Code Playgroud)
C标准指定具有自动存储持续时间的未初始化变量具有不确定的值,该值是未指定的或陷阱表示.它还指定uintN_t类型没有填充位,并且定义了值的大小和范围; 所以陷阱表示uint64_t是不可能的.
所以我得出结论,未初始化的值本身并不是未定义的行为.读它怎么样?
6.3.2.1左值,数组和函数指示符
- ...
除非它是运算
sizeof符的操作数,_Alignof运算符,一元&运算符,++运算符,--运算符或者左运算符.运算符或赋值运算符,没有数组类型的左值被转换为存储在指定对象中的值(并且不再是左值); 这称为左值转换....... 如果左值指定了一个自动存储持续时间的对象,该对象可以使用寄存器存储类声明(从未使用过其地址),并且该对象未初始化(未使用初始化程序声明并且未对其进行任何赋值)在使用之前),行为是未定义的.
- 除非它是sizeof运算符,_Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则将具有类型''数组类型''的表达式转换为表达式输入''指向类型'的指针,指向数组对象的初始元素,而不是左值.如果数组对象具有寄存器存储类,则行为未定义.
问题:下标数组是否计为获取对象的地址?
下面的文字似乎暗示下标数组需要转换为指针,如果没有获取地址似乎无法做到:
6.5.2.1数组下标
约束
- 其中一个表达式应具有类型''指向完整对象类型'的指针,另一个表达式应具有整数类型,结果具有类型''type''.
语义
- 后缀表达式后跟方括号[]中的表达式是数组对象元素的下标名称.下标运算符[]的定义是E1 [E2]与(*((E1)+(E2)))相同.由于适用于binary +运算符的转换规则,如果E1是数组对象(等效地,指向数组对象的初始元素的指针)并且E2是整数,则E1 [E2]指定E2-元素E1(从零开始计数).
这使§6.3.2.1第3段看起来很奇怪.如果订阅需要转换为指针,那么数组怎么可以注册存储类呢?
如何在C(而不是C++)中定义常量对象的常量数组?
我可以定义
int const Array [] = {
/* init data here */
};
Run Code Online (Sandbox Code Playgroud)
但这是一个非常数对象的非常数.
我可以用
int const * const Array = {
/* init data here */
};
Run Code Online (Sandbox Code Playgroud)
它可能会奏效.但是有可能使用数组语法吗?(看起来更干净)
背景
我有一个带有配置头文件的C项目,例如:
// config.h
#define FEATURE_1_AVAILABLE 1
#define FEATURE_2_AVAILABLE 0
#define FEATURE_3_AVAILABLE 1
Run Code Online (Sandbox Code Playgroud)
模块使用这些标志在构建中包括/排除功能:
#include "config.h"
void foo(void) {
...
#if FEATURE_1_AVAILABLE
useFeature1();
#endif
...
Run Code Online (Sandbox Code Playgroud)
有不同版本的config.h不同版本。
问题
#include "config.h" 被意外删除,因此即使在config中启用了该功能,该功能也未处于活动状态。
不幸的是,它会#if FEATURE_1_AVAILABLE默默地评估0未定义的时间。因此,如果未定义,我需要一个错误。
选项1
我可以在每个条件上添加额外的“如果定义”测试。
#ifndef FEATURE_1_AVAILABLE
#error No feature 1
#elif FEATURE_1_AVAILABLE
useFeature1();
#endif
Run Code Online (Sandbox Code Playgroud)
缺点是一个功能标记可能会在模块中的许多不同位置进行测试,并且添加多条预处理程序行不会使代码更漂亮。
选项2
在模块的开头添加单个测试:
#ifndef FEATURE_1_AVAILABLE
#error No feature 1
#endif
Run Code Online (Sandbox Code Playgroud)
但这可能会因为相同的原因而丢失/遗忘#include "config.h"。
选项3
将标志定义为宏:
#define FEATURE_1_AVAILABLE() 1
Run Code Online (Sandbox Code Playgroud)
并用作:
#if FEATURE_1_AVAILABLE()
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果您忘记括号,这也将无声地失败:
#if FEATURE_1_AVAILABLE
Run Code Online (Sandbox Code Playgroud)
选项X …
我有一个嵌入式 C 项目,正在使用 eclipse 进行编译。我需要将二进制文件作为常量数组读入应用程序代码。
该二进制文件约为 200kB,需要成为应用程序代码的一部分,以便应用程序代码可以随时读取二进制映像并将其加载到板上需要此初始化映像的另一个设备中。
我通常会将图像加载到板上的非易失性存储器中,然后读取并移动它,但这在这里不可行,它必须是可执行图像的一部分。
我可以在 makefile 中通过将 .bin 文件链接到某个地址来完成此操作,或者在 C 代码中执行此操作,例如
const char binFileImage [] = { file.bin };
Run Code Online (Sandbox Code Playgroud)
这显然行不通,但我还没有想出可行的语法。
仅供参考,file.bin确实是一个二进制文件。
关于如何做到这一点有什么想法吗?
我正在尝试将离子类添加到我的Angular 4应用程序中.以下是采取的步骤:
我错过了somrthing吗?
在大多数情况下,一切都正常,它可以构建无错误.但是,当我尝试运行它时,它似乎崩溃了.更具体地说,每当我启动代码并按"a"或"b"时,程序就会崩溃.有人能告诉我如何解决这个问题吗?
#include <stdio.h>
#include <string.h>
int top=-1;
int word;
char stack_string[100];
void push(char word);
char pop(void);
int main()
{
char input;
char str[100];
int i;
printf("press [a] for palindrome check, [b] for string reversal:");
scanf("%s", input);
if (input == 'b'){
printf("Input a string: ");
scanf("%[^\n]s", str);
for(i=0;i<strlen(str);i++)
push(str[i]);
for(i=0;i<strlen(str);i++)
str[i]=pop();
printf("Reversed String is: %s\n",str);
}
else if(input == 'a'){
char str[100];
int count = 0;
printf("Input a string: ");
scanf("%[^\n]s", str);
for (i = 0; i < strlen(str); i++)
{ …Run Code Online (Sandbox Code Playgroud) #include <stdio.h>
int main()
{
printf("%.2g %.2f\n", 2.925, 2.925);
}
Run Code Online (Sandbox Code Playgroud)
我认为正确的输出应该是:
2.93 2.93
Run Code Online (Sandbox Code Playgroud)
现在,输出如下:
2.9 2.92
Run Code Online (Sandbox Code Playgroud)
有两个误解:
为什么 '%.2g' 不显示点后的两位数?
为什么四舍五入?