C `strtoul()`very的正确返回值是多少?';“否定”;串?
这是一个很好的例子。 我研究了这个问题,发现结果很奇怪,并公布了我的发现C `strtoul()`very的正确返回值是多少?';“否定”;串?,c,C,这是一个很好的例子。 我研究了这个问题,发现结果很奇怪,并公布了我的发现 “非常负”字符串应该从strtoul():1,ULONG_MAX返回什么值 strtol() 对于表示数值的字符串,如“123”,strtol()的行为与预期一致。字符串(蓝色)[LONG\u MIN…LONG\u MAX]转换为预期的LONG值。LONG\u MAX上方的字符串(黄色)转换为LONG\u MAX并设置errno==ERANGE。LONG\u MIN下面的字符串转换为LONG\u MIN并设置errno
“非常负”字符串应该从
strtoul()
:1
,ULONG_MAX
返回什么值
strtol()
对于表示数值的字符串,如“123”
,strtol()
的行为与预期一致。字符串(蓝色)[LONG\u MIN…LONG\u MAX]
转换为预期的LONG
值。LONG\u MAX
上方的字符串(黄色)转换为LONG\u MAX
并设置errno==ERANGE
。LONG\u MIN
下面的字符串转换为LONG\u MIN
并设置errno==ERANGE
strtoul()
positive
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
long strtol_test(const char *s, int base) {
printf("\n");
int width = snprintf(NULL, 0, "%ld", LONG_MIN);
printf("base:%2d \"%s\"\n", base, s);
char *endptr_signed;
errno = 0;
long val_signed = strtol(s, &endptr_signed, base);
int errno_signed = errno;
char *endptr_unsigned;
errno = 0;
unsigned long val_unsigned = strtoul(s, &endptr_unsigned, base);
int errno_unsigned = errno;
if (val_signed < 0 || (unsigned long) val_signed != val_unsigned
|| endptr_signed != endptr_unsigned || errno_signed != errno_unsigned) {
printf(" signed val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
printf("unsigned val:%*lu end:%2td e:%s\n", width, val_unsigned,
endptr_unsigned - s, strerror(errno_unsigned));
return 1;
}
printf(" both val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
return 0;
}
int main() {
char s[][50] = {"-ULONG_MAX1", "-ULONG_MAX", "LONG_MIN1", "LONG_MIN", "-1",
"-0", "42", "LONG_MAX", "LONG_MAX1", "ULONG_MAX", "ULONG_MAX1", "x"};
snprintf(s[0], sizeof *s, "-%lu", ULONG_MAX);
s[0][strlen(s[0]) - 1]++;
snprintf(s[1], sizeof *s, "-%lu", ULONG_MAX);
snprintf(s[2], sizeof *s, "%ld", LONG_MIN);
s[2][strlen(s[2]) - 1]++;
snprintf(s[3], sizeof *s, "%ld", LONG_MIN);
snprintf(s[7], sizeof *s, "%ld", LONG_MAX);
snprintf(s[8], sizeof *s, "%ld", LONG_MAX);
s[8][strlen(s[8]) - 1]++;
snprintf(s[9], sizeof *s, "%lu", ULONG_MAX);
snprintf(s[10], sizeof *s, "%lu", ULONG_MAX);
s[10][strlen(s[10]) - 1]++;
strcpy(s[11], s[0]);
s[11][strlen(s[11]) - 1]++;
int n = sizeof s / sizeof s[0];
for (int i = 0; i < n; i++) {
strtol_test(s[i], 0);
}
}
对于表示数值的字符串,如“123”
,strtoul()
,其行为也符合预期。字符串(红色)[0…ULONG_MAX]
转换为预期的无符号长字符串值。ULONG_MAX
上方的字符串(绿色)转换为ULONG_MAX
并设置errno==ERANGE
如果主题序列以减号开头,则转换产生的值将被求反(在返回类型中)。C17dr§7.22.1.4 5
strtoul()
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
long strtol_test(const char *s, int base) {
printf("\n");
int width = snprintf(NULL, 0, "%ld", LONG_MIN);
printf("base:%2d \"%s\"\n", base, s);
char *endptr_signed;
errno = 0;
long val_signed = strtol(s, &endptr_signed, base);
int errno_signed = errno;
char *endptr_unsigned;
errno = 0;
unsigned long val_unsigned = strtoul(s, &endptr_unsigned, base);
int errno_unsigned = errno;
if (val_signed < 0 || (unsigned long) val_signed != val_unsigned
|| endptr_signed != endptr_unsigned || errno_signed != errno_unsigned) {
printf(" signed val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
printf("unsigned val:%*lu end:%2td e:%s\n", width, val_unsigned,
endptr_unsigned - s, strerror(errno_unsigned));
return 1;
}
printf(" both val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
return 0;
}
int main() {
char s[][50] = {"-ULONG_MAX1", "-ULONG_MAX", "LONG_MIN1", "LONG_MIN", "-1",
"-0", "42", "LONG_MAX", "LONG_MAX1", "ULONG_MAX", "ULONG_MAX1", "x"};
snprintf(s[0], sizeof *s, "-%lu", ULONG_MAX);
s[0][strlen(s[0]) - 1]++;
snprintf(s[1], sizeof *s, "-%lu", ULONG_MAX);
snprintf(s[2], sizeof *s, "%ld", LONG_MIN);
s[2][strlen(s[2]) - 1]++;
snprintf(s[3], sizeof *s, "%ld", LONG_MIN);
snprintf(s[7], sizeof *s, "%ld", LONG_MAX);
snprintf(s[8], sizeof *s, "%ld", LONG_MAX);
s[8][strlen(s[8]) - 1]++;
snprintf(s[9], sizeof *s, "%lu", ULONG_MAX);
snprintf(s[10], sizeof *s, "%lu", ULONG_MAX);
s[10][strlen(s[10]) - 1]++;
strcpy(s[11], s[0]);
s[11][strlen(s[11]) - 1]++;
int n = sizeof s / sizeof s[0];
for (int i = 0; i < n; i++) {
strtol_test(s[i], 0);
}
}
对于字符串(红色)[-ULONG_MAX…-1]
,转换将否定正转换并添加ULONG_MAX+1
(类似于将负值指定给无符号字符串的典型情况),并且不会设置errno
。这有点令人惊讶,但规范就是这样定义的
strtoul()
非常负面-问题
对于小于-ULONG_MAX
的字符串(绿色),我希望转换可以像上面描述的较小负值一样处理:转换将否定正转换(ULONG_MAX
由于溢出),并添加ULONG_MAX+1
。预期结果1
(或者可能0
)为errno==ERANGE
。然而,练习strtoul()
会导致ULONG\u MAX
什么是正确的
测试代码
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
long strtol_test(const char *s, int base) {
printf("\n");
int width = snprintf(NULL, 0, "%ld", LONG_MIN);
printf("base:%2d \"%s\"\n", base, s);
char *endptr_signed;
errno = 0;
long val_signed = strtol(s, &endptr_signed, base);
int errno_signed = errno;
char *endptr_unsigned;
errno = 0;
unsigned long val_unsigned = strtoul(s, &endptr_unsigned, base);
int errno_unsigned = errno;
if (val_signed < 0 || (unsigned long) val_signed != val_unsigned
|| endptr_signed != endptr_unsigned || errno_signed != errno_unsigned) {
printf(" signed val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
printf("unsigned val:%*lu end:%2td e:%s\n", width, val_unsigned,
endptr_unsigned - s, strerror(errno_unsigned));
return 1;
}
printf(" both val:%*ld end:%2td e:%s\n", width, val_signed,
endptr_signed - s, strerror(errno_signed));
return 0;
}
int main() {
char s[][50] = {"-ULONG_MAX1", "-ULONG_MAX", "LONG_MIN1", "LONG_MIN", "-1",
"-0", "42", "LONG_MAX", "LONG_MAX1", "ULONG_MAX", "ULONG_MAX1", "x"};
snprintf(s[0], sizeof *s, "-%lu", ULONG_MAX);
s[0][strlen(s[0]) - 1]++;
snprintf(s[1], sizeof *s, "-%lu", ULONG_MAX);
snprintf(s[2], sizeof *s, "%ld", LONG_MIN);
s[2][strlen(s[2]) - 1]++;
snprintf(s[3], sizeof *s, "%ld", LONG_MIN);
snprintf(s[7], sizeof *s, "%ld", LONG_MAX);
snprintf(s[8], sizeof *s, "%ld", LONG_MAX);
s[8][strlen(s[8]) - 1]++;
snprintf(s[9], sizeof *s, "%lu", ULONG_MAX);
snprintf(s[10], sizeof *s, "%lu", ULONG_MAX);
s[10][strlen(s[10]) - 1]++;
strcpy(s[11], s[0]);
s[11][strlen(s[11]) - 1]++;
int n = sizeof s / sizeof s[0];
for (int i = 0; i < n; i++) {
strtol_test(s[i], 0);
}
}
对于strtoul()
,范围错误结果始终为ULONG\u MAX
这相当简单,对于像“-18446744073709551616”
这样的字符串,由于正确的(正)值超出范围,因此返回ULONG_MAX
,并将errno
设置为ERANGE
。对于提供任何其他答案的strtoul()
范围错误,不存在任何规定
。。。如果正确值超出可表示值的范围<代码>ULONG_MAX
。。。返回(根据返回类型和值的符号,如果有),宏ERANGE
的值存储在errno
中。C17dr§7.22.1.4 8
因此,当字符串在
[-ULONG\u MAX…+ULONG\u MAX]
范围内时,strtoul()
生成一个非错误值。转换后的结果是一个无符号长[0…ULONG_MAX]
。错误结果总是ULONG\u MAX
对于strtoul()
,范围错误结果总是ULONG\u MAX
这相当简单,对于像“-18446744073709551616”
这样的字符串,由于正确的(正)值超出范围,因此返回ULONG_MAX
,并将errno
设置为ERANGE
。对于提供任何其他答案的strtoul()
范围错误,不存在任何规定
。。。如果正确值超出可表示值的范围<代码>ULONG_MAX。。。返回(根据返回类型和值的符号,如果有),宏ERANGE
的值存储在errno
中。C17dr§7.22.1.4 8
因此,当字符串在[-ULONG\u MAX…+ULONG\u MAX]
范围内时,strtoul()
生成一个非错误值。转换后的结果是一个无符号长[0…ULONG_MAX]
。错误结果总是ULONG\u MAX