字符*a,*b; (ba) 是什么类型以及如何打印它?

发布于 2024-08-09 04:06:45 字数 182 浏览 7 评论 0原文

{
  char *a, *b;

  printf("%lx\n",(b-a));
}

通常可以工作,事实上,我无法想象它在 32 位或 64 位机器上发出警告或失败。但这对于 ANSI C 和大小认识来说是正确的做法吗?我希望这段代码能够在所有可能的平台上运行,包括非 Unix 和嵌入式系统。

{
  char *a, *b;

  printf("%lx\n",(b-a));
}

Usually works, in fact, I can't imagine it giving a warning or failing on a 32-bit or 64-bit machine. But is that the proper thing to do for ANSI C and size awareness? I'd like this code to work on every platform possible, including non-Unixes and embedded systems.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

别理我 2024-08-16 04:06:45

b - aptrdiff_t,您可以使用 %tdprintf 格式打印它。根据规范第 6.5.6 节加法运算符

当两个指针相减时,两个指针都应指向同一个数组对象的元素,或者指向数组对象最后一个元素之后的一个;结果是两个数组元素的下标之差。结果的大小是实现定义的,其类型(有符号整数类型)是 中定义的 ptrdiff_t标头。

对于 printf 和相关函数,第 7.19.6 节格式化输入/输出函数

t 指定后面的 di< /strong>、oux > 或 X 转换说明符适用于 ptrdiff_t 或相应的无符号整数类型参数;或者后面的 n 转换说明符适用于指向 ptrdiff_t 参数的指针。


我又仔细研究了规范,似乎表明两个指针的差异甚至可能不适合 ptrdiff_t ,在这种情况下,行为是未定义的:

J.2 未定义行为
- 两个指针相减的结果无法在 ptrdiff_t 类型的对象中表示 (6.5.6)。

尽管我无法想象可能出现的任何实现。我想您可以检查 中的 PTRDIFF_MINPTRDIFF_MAX 来确定。

b - a is a ptrdiff_t, which you can print with %td in your printf format. From the spec section 6.5.6 Additive operators:

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header.

For printf and related functions, section 7.19.6 Formatted input/output functions:

t Specifies that a following d, i, o, u, x, or X conversion specifier applies to a ptrdiff_t or the corresponding unsigned integer type argument; or that a following n conversion specifier applies to a pointer to a ptrdiff_t argument.

I poked around in the spec some more, and it seems to indicate that a difference of two pointers might not even fit in a ptrdiff_t, in which case behaviour is undefined:

J.2 Undefined behavior
- The result of subtracting two pointers is not representable in an object of type ptrdiff_t (6.5.6).

Though I can't imagine any implementation where that might come up. I guess you could check PTRDIFF_MIN and PTRDIFF_MAX in <stdint.h> to be really sure.

深空失忆 2024-08-16 04:06:45

仅当 ab 都指向同一 char 数组的元素时才定义 b - a 的结果。此要求也可以解释为 ab 指向属于同一对象的字节,因为每个对象都可以重新解释为 char 数组。

否则,结果是不确定的。即尝试减去此类指针会导致未定义的行为。

当结果被定义时,它具有 ptrdiff_t 类型。 ptrdiff_t 是一个 typedef 名称,该 typedef 名称后面隐藏的类型是实现定义的。但已知该类型是有符号的。

另请注意,C 语言不保证 ptrdiff_t 足够大以容纳任何减法的结果,即使指针指向同一数组的元素也是如此。如果指针相距太远,ptrdiff_t 类型无法容纳结果,则行为未定义。

即使在 C99 中,ptrdiff_t 也没有特定的 printf 格式说明符,因此您最好将其转换为足够大的有符号整数类型,并为此使用格式说明符类型

printf("%ld\n", (long) (b - a));

更正: C99 确实有一个 ptrdiff_t 的长度修饰符。在 C99 中打印结果的正确方法是

printf("%td\n", b - a);

注意 t 是长度修饰符。它可以与douxX转换结合使用说明符,具体取决于您想要获得的输出格式。在 C89/90 中,您仍然必须坚持使用足够大的有符号类型。

PS 你说你无法想象它在 32 位或 64 位机器上失败。事实上,很容易想象(或实际实现)失败。您会看到 32 位机器上的 ptrdiff_t 通常是 32 位类型。由于它是有符号类型,因此只有 31 位可用于表示值的大小。如果你取两个相距较远的指针(即需要32位来表示“距离”),b - a的结果将会溢出并且毫无意义。为了防止出现此故障,您在 32 位计算机上至少需要 33 位签名的 ptrdiff_t,在 64 位计算机上至少需要 65 位签名的 ptrdiff_t机器。实现通常不会这样做,它们只是使用标准中的“权限”来在溢出时产生未定义的行为。

The result of b - a is only defined when both a and b point to elements of the same char array. This requirement can also be interpreted as a and b pointing to bytes belonging to the same object, since every object can be re-interpreted as a char array.

Otherwise, the result is undefined. I.e. an attempt to subtract such pointers results in undefined behavior.

When the result is defined, it has ptrdiff_t type. ptrdiff_t is a typedef name and what type is hiding behind that typedef name is implementation-defined. The type is known to be signed though.

Also note, that C language does not guarantee that ptrdiff_t is large enough to hold the result of any subtraction, even if the pointers are pointing to the elements of the same array. If the pointers are too far apart for the type ptrdiff_t to accomodate the result, the behavior is undefined.

There's no specific printf format specifier for ptrdiff_t even in C99, so you'll probably be better off converting it to a sufficiently large signed integer type and use a format specifier for that type

printf("%ld\n", (long) (b - a));

Correction: C99 does have a length modifier for ptrdiff_t. The proper way to print the result in C99 would be

printf("%td\n", b - a);

Note that t is a length modifier. It can be combined with d, o, u, x or X conversion specifiers, depending on what output format you want to obtain. In C89/90 you would still have to stick with using a sufficiently large signed type.

P.S. You said that you can't imagine it failing on a 32-bit or 64-bit machine. In fact, it is very easy to imagine (or to actually make it) fail. You see the ptrdiff_t on a 32-bit machine is usually a 32-bit type. Since it is a signed type, it has only 31 bit available to represent the magnitude of the value. If you take two pointers that are farther apart (i.e. require 32 bits to represent the "distance"), the result of b - a will overflow and will be meaningless. In order to prevent this failure you'd need at least 33-bit signed ptrdiff_t on a 32-bit machine, and at least 65-bit signed ptrdiff_t on 64-bit machine. Implementations normally don't do that, they just use the "permission" from the standard to produce undefined behavior on the overflow.

ヤ经典坏疍 2024-08-16 04:06:45

它是 ptrdiff_t。来自 man stddef.h

ptrdiff_t
              Signed integer type of the result of subtracting two pointers.

使用 %td 打印它。

It's ptrdiff_t. From man stddef.h:

ptrdiff_t
              Signed integer type of the result of subtracting two pointers.

Print it with %td.

§对你不离不弃 2024-08-16 04:06:45

ba 的类型为 ptrdiff_t

The type of b-a is ptrdiff_t

∞琼窗梦回ˉ 2024-08-16 04:06:45

由于您尚未初始化变量 ab,因此代码会给出未定义的行为。但除此之外,ba的类型是ptrdiff_t,它足够大以包含结果。如果你有足够现代的 C,你可以使用 %tx 来打印它。

如果您不想使用 %tx,您应该转换您的结果,使其实际上与您的格式说明符匹配(而不是偶然):

printf("%lx", (unsigned long)(a-b));

系统可能具有例如32 位地址空间和 32 位 ptrdiff_t,但长度是 64 位,然后你的 printf 就会失败。

Since you haven't initialized the variables a and b, the code gives undefined behavior. But other than that, the type of b-a is ptrdiff_t, which is big enough to contain the result. If you have a modern enough C, you can printf it with %tx.

If you don't want to use %tx, you should convert your result so it actually matches (and not just by accident) your format specifier:

printf("%lx", (unsigned long)(a-b));

It is not inconceivable that a system could have for example a 32-bit address space, and a 32-bit ptrdiff_t, but a 64-bit long, and then your printf would fail.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文