小编pab*_*977的帖子

操作员间接禁止(或不?)定义整数常量表达式(在C中)

在标准C(C99/C11)中,我们有所谓的整数常量表达式,它们是常量表达式,其操作数都是常量整数.

以下定义适用:

标准C99,第6.6节(第6节):

整数常量表达式)应具有整数类型,并且只能具有整数常量,操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量.

标准C99

这在更一般的常量表达式的定义之后出现.
(由于在常量表达式之后定义了整型常量表达式,我假设前者是最后一个的特殊情况.)

另一方面,条件表达式被视为常量表达式,受以下规则约束:

标准C99,第6.6节:

常量表达式不应包含赋值,递增,递减,函数调用或逗号运算符,除非它们包含在未评估的子表达式中.

通过展开条件表达式的含义,我们可以归结为后缀表达式和/或一元表达式.

现在,如果我们将这些约束应用于整数常量表达式,我们粗略地得到它们由条件表达式组成,这些条件表达式的限制使得每个操作数都是整数/枚举/字符常量(或浮动常量紧跟在强制转换之前),并且没有赋值,递增,递减,函数调用或逗号运算符.

  • 简单来说,让我们假设E是一个这样的表达式,没有任何sizeof运算符,也没有未计算的操作数.

我的问题是:E中
是否间接禁止以下操作员:

  • & (地址),
  • * (间接),
  • [] (数组下标),
  • . (结构成员),
  • -> (指向struct成员的指针).

另外,复合文字是否也被禁止?

备注:我有兴趣回答严格符合程序的问题(C99/C11).

我认为它们不能处于E的任何子表达式中,但我不确定这是否完全正确.我的快速推理如下:

  • 如果FE的整数常量子表达式,则根据定义F具有整数类型T.
  • 如果一元运算符&出现在E中的F之前,则&F输入一个操作数,其类型为"指向T的指针",这在E中是不允许的(尽管F不是一个对象,但只是一个整数值,所以不能应用).因此不能出现在任何E中 …

c syntax c99 language-lawyer

13
推荐指数
1
解决办法
307
查看次数

在C中用宏创建假函数可以多少钱?

人们总是说宏是不安全的,而且它们不是(直接)对其参数进行类型检查,等等.更糟糕的是:当发生错误时,编译器会给出内在和难以理解的诊断,因为宏只是一团糟.

是否有可能以与函数几乎相同的方式使用宏,通过安全的类型检查,避免典型的陷阱以及编译器提供正确诊断的方式.

  1. 我将以肯定的方式回答这个问题(自动回答).
  2. 我想向您展示我在这个问题上找到的解决方案.
  3. 标准C99将被使用和尊重,以具有统一的背景.
  4. 但是(显然有一个"但是"),它将"定义"人们必须"吃"的某种"语法".
  5. 这种特殊语法旨在最简单地编写,最容易理解和/或处理,最大限度地降低生成错误的程序的风险,更重要的是,从编译器获取正确的诊断消息.
  6. 最后,它将研究两种情况:"非返回值"宏(简单情况)和"返回值"宏(不容易,但更有趣的情况).

让我们快速记住宏生成的一些典型陷阱.

例1

#define SQUARE(X) X*X
int i = SQUARE(1+5);
Run Code Online (Sandbox Code Playgroud)

预期值i:36.真值i:11(宏观扩展:) 1+5*1+5.陷阱!

(典型)解决方案(例2)

#define SQUARE(X) (X)*(X)
int i = (int) SQUARE(3.9);
Run Code Online (Sandbox Code Playgroud)

预期价值i:15.真实价值i:11(宏观扩张后:(int) (3.9)*(3.9)).陷阱!

(典型)解决方案(例3)

#define SQUARE(X) ((X)*(X))
Run Code Online (Sandbox Code Playgroud)

它适用于整数和浮点数,但它很容易被破坏:

int x = 2;
int i = SQUARE(++x);
Run Code Online (Sandbox Code Playgroud)

预期值i:9(因为(2+1)*(2+1)...).真值i:12(宏扩展:((++x)*(++x)),给出3*4).陷阱!

在这里可以找到一种很好的宏检查方法:

但是我想要更多:某种界面或"标准"语法,以及(少量)易于记忆的规则.意图是"能够使用(不实现)宏"与尽可能类似的功能.这意味着:写得好的假函数.

为什么在某种程度上有趣?

我认为这是在C中实现的一个有趣的挑战. …

c macros c99

9
推荐指数
1
解决办法
1683
查看次数

关于转换为整数常量表达式(在标准C中)

在标准C(我的意思是C99或C11)中,我们有所谓的整数常量表达式,它们是常量表达式,其操作数都是常量整数.还有其他约束,以避免表达式中的逗号运算符.

但是,在某些特殊情况下,允许使用其他非整数对象(甚至是非常量对象).
例如,如果将sizeof运算符应用于大小在转换时间中已知的对象,则允许将其作为整数常量表达式的一部分(请注意,sizeof始终返回整数值).

此外,有时也允许显式转换为整数类型.
标准C99建立以下规则:

标准C99,第6.6节(第6节):

整数常量表达式)应具有整数类型,并且只能具有整数常量,操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量.

标准C99

我的问题是: "浮动常数是演员的直接操作数"的确切含义是什么?

浮点常数类似于3.14e + 3,或者是0x2.11p-5.
也就是说,不是float类型的一般常量表达式,而只是浮点文字.
然后,我明白在上面的定义中只允许这样的事情:

 (int) 3.14
Run Code Online (Sandbox Code Playgroud)

但是不允许涉及浮动文字的操作.
这排除了以下情况:

 (int) -3.14  /* The minus sign is not part of the constant: it is an operator */
 (int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */
Run Code Online (Sandbox Code Playgroud)

最后一种情况不需要在转换时间中执行任何浮点算术运算,并且相当于没有括号:(int) 3.14.
但是,它不是演员直接操作数.

那么,我们是否必须考虑那(int) (3.14)是[有效整数常量表达式的一部分] (根据定义)?

另一方面,编译器GCC(带选项:-std …

c syntax c99 language-lawyer

9
推荐指数
1
解决办法
1194
查看次数

是否可以隐藏标准标题的一部分(在C中)?

我想做一些看似不可能的事情.

我想写3个文件:main.c,foo.h,foo.c.
我们的想法是在foo.hfoo.c中定义一个结构,使其成员在main.c中可见.其中一个struct成员具有FILE标准头中定义的类型<stdio.h>.但是<stdio.h>必须在main.c文件中保持不可见的函数和宏.

该解决方案必须符合标准C(C99和/或C11)和便携式.那可能吗?

标题foo.hmain.cfoo.c中都是#included .
标准头文件<stdio.h>仅在foo.c中包含#included ,但在main.c中不包含.

我想声明struct如下:

struct myfile_s {
   FILE *F;
   char *filename;
   char buff[100];
} myfile;
Run Code Online (Sandbox Code Playgroud)

对于以下内容,只有成员FILE *F才是重要的.
结构myfile将由foo.c中出现的函数初始化和修改.
目的是myfile通过foo.h中extern声明的函数对文件进行操作,而foo.h中的函数又必须在foo.c中定义.

文件操作涉及标准函数<stdio.h>,但这些函数必须隐藏在main.c文件中.但是,我想直接从main.c访问到成员 …

c

7
推荐指数
2
解决办法
171
查看次数

long_double_t 是否存在(标准 C: C23)

新标准C(ISO/IEC 9899:2023,又名C23),
在附录H中,定义了几个宏和类型,
相对于实数和复数算术,
并符合 ISO/IEC 60559 标准(浮点算术)。

根据 H.1 小节,存在三个
实现定义的宏来测试
与附件 H 定义的一致性。

__STDC_IEC_60559_TYPES__  
__STDC_IEC_60559_BFP__  
__STDC_IEC_60559_DFP__  
Run Code Online (Sandbox Code Playgroud)

此外,要“激活”关联的宏和类型,
用户必须定义​​宏:

__STDC_WANT_IEC_60559_TYPES_EXT__  
Run Code Online (Sandbox Code Playgroud)

该标准的措辞在几个细节上很明确:

  • 如果__STDC_IEC_60559_BFP__是由编译器定义的,则意味着_FloatN,_FloatN_t和其他_FloatN*类型也已定义。
  • 如果__STDC_IEC_60559_DFP__是由编译器定义的,则意味着_DecimalN,_DecimalN_t和其他_DecimalN*类型也已定义。
  • __STDC_IEC_60559_TYPES__无论哪种情况,都会定义宏。
  • 如果定义了宏,则意味着至少定义了__STDC_IEC_60559_TYPES__一个宏__STDC_IEC_60559_BFP__或(或两者)。__STDC_IEC_60559_DFP__

在 H.11 小节中,类型long_double_t被添加到 中<math.h>

long_double_t但是,我无法推断在哪些条件下可以确保给定实现中的存在。

问题:

如果__STDC_IEC_60559_TYPES__已定义,是否足以确定long_double_t也在 中定义<math.h>

我的怀疑来自以下可能出现的特殊情况:

  • __STDC_IEC_60559_TYPES____STDC_IEC_60559_DFP__已定义,但__STDC_IEC_60559_BFP__未定义。

在本例中,定义了十进制类型。
但是,long_double_t不是十进制类型。

子问题:
宏是否 …

c language-lawyer c23

7
推荐指数
1
解决办法
121
查看次数

C++工作草案的措辞可能有缺陷(整数转换等级规则)

我在标准 C++工作草案中发现了一个可能的矛盾。我首先陈述事实,我的问题在最后。

整数转换等级建立时,[conv.rank]/1.1表示

任何两个有符号整数类型 [...] 不应具有相同的整数转换等级,即使它们具有相同的表示。

[basic.fundamental]/8说:

Typewchar_t是一种独特的类型,它具有实现定义的有符号或无符号整数类型作为其基础类型。

最后,[conv.rank]/1.8

的行列char8_tchar16_tchar32_t,和wchar_t应等于其基础类型的行列([basic.fundamental])。

如果它wchar_t被实现为有符号整数类型,它将与它的底层类型具有相同的等级,它是一些其他整数类型的不同类型。

因此,我们有两个具有相同等级的不同有符号整数类型,与 [conv.rank]/1.1 相矛盾。

这是一个实际的矛盾,还是我误解了 C++ 中两个可简单复制的类型是不同的类型?

c++ wchar-t language-lawyer c++20

4
推荐指数
1
解决办法
82
查看次数

如何在BMP文件结构中定义数据类型FXPT2DOT30?

根据Microsoft提供的定义,FXPT2DOT30类型出现在为BMP文件定义结构CIEXYZ时:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd371828(v=vs.85).aspx

但是,我无法在任何地方找到FXPT2DOT30的确切定义.它的确切定义是什么?应该保留什么样的数据?

bmp

2
推荐指数
1
解决办法
794
查看次数

指向标准C中的整数转换的指针

我在这个网站上已经阅读了几个关于这个主题的问题,但我仍然有疑问.

在标准C中,我们可以阅读:

6.3.2.3.p.5:整数可以转换为任何指针类型.[...]
6.3.2.3.p.6:任何指针类型都可以转换为整数类型.[...].

省略的文本(将放在括号[...]中)只讨论转换失败时可能发生的问题.

但是我的问题更为笼统:

  1. 我观察到整数数学数字是无限的一组值.
  2. C中的任何整数类型只能表示整数数学值的有限子集.
  3. 在第6.3.2.3.p5/p6段中,似乎标准C11假定"每个指针值都可以映射到整数数学值 ".
  4. 此外,编辑C11标准的方式似乎表明,只有当这个数学(或抽象)值无法以开发人员选择的预期整数类型表示时,无论出于何种原因,都是在操作失败时.

我的问题是:我的解释(3)是正确的吗?

另一方面,当我们定义一个大小为N的类型T的数组时, 由于我们可以对数组的位置进行整数运算, 因此很明显,至少在"本地"级别,在数组中, 我们有相应的数组内存块的 运算方式与从0N-1的数字集相同.



通过定义数组或分配的对象,我们可以确定,在C中,
内存地址可以被"本地"视为算术上等同于整数的子集.

然而,这种"局部"行为不足以得出
标准C假设存储器模型的结论,该存储器模型的存储器地址可被视为"仅一个且同一组整数"的一部分.

然而,6.3.2.3.p5/p6似乎"暗示"这个更强大的断言,尽管我并不完全确定.

另一个问题可能会带来更多亮点:

  • 是在标准C的可能性,即两个不同的有效指针开放p,q,(即:p != q)中,当转换成整数型,所得到的整数值变得相等.

c pointers c99 language-lawyer c11

0
推荐指数
1
解决办法
1118
查看次数

标签 统计

c ×6

language-lawyer ×5

c99 ×4

syntax ×2

bmp ×1

c++ ×1

c++20 ×1

c11 ×1

c23 ×1

macros ×1

pointers ×1

wchar-t ×1