RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-262953

wololo's questions

Martin Hope
wololo
Asked: 2022-03-22 03:32:28 +0000 UTC

使用 strtol() / strtoll() 函数及其无符号对应物将字符串转换为整数的算法

  • 3

我对通过函数strtol(),strtoll() , strtoul(),strtoull()将 C 字符串转换为整数类型的算法感兴趣。

让我们从 C 语言标准(n1570, 7.22.1.4)开始:

、strtol、strtoll和函数[ strtoul... ] 5 如果主题序列具有预期的形式并且 的值为零,则根据 6.4.4.1 的规则,从第一位数字开始的字符序列被解释为整数常量. 如果主题序列具有预期的形式并且 的值介于 2 和 36 之间,则将其用作转换的基础,将其值赋予每个字母,如上所示。如果主题序列以减号开头,则转换产生的值被否定(在返回类型中)。指向最终字符串的指针存储在 指向的对象中,前提是它不是空指针。 [... ] , ,strtoull
long int strtol(const char * restrict nptr, char ** restrict endptr, int base);

basebaseendptrendptr

Returns
strtolstrtollstrtoul, 并且strtoull函数返回转换后的值(如果有)。如果无法执行转换,则返回零。如果正确的值在可表示值的范围之外,LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, 或者ULLONG_MAX返回(根据返回类型和值的符号,如果有的话),宏的值ERANGE存储在errno.

据我了解所写内容,想法如下(不考虑非十进制基数的前导空格字符和数字系统):

  1. 在源代码行中,我们将丢弃减号(如果有)。
  2. 如果字符串包含目标类型无法表示的数字,则返回 LONG_MIN,LONG_MAX依此类推。取决于目标类型和字符串中数字的符号。并且还安装errno在ERANGE.
  3. 让我们将字符串转换为目标类型。
  4. 如果源字符串中的数字以减号开头,则将减号应用于目标类型中的值。

示例 #1

errno = 0;
unsigned long long ullval = std::strtoull("-18446744073709551615", nullptr, 10);
cout << "errno:  " << errno   << endl;
cout << "ullval: " << ullval  << endl;

cout << -18446744073709551615ULL << endl;

结论:

errno:  0
ullval: 1
1

现在没关系。

  1. "-18446744073709551615"减号已从行中删除。
  2. 字符串"18446744073709551615"中的数字由 type 表示unsigned long long。
  3. 让我们将字符串转换为数字。
  4. 对结果类型中的值应用减号:-18446744073709551615ULL == 1ULL。

示例 #2

和上一个类似,只是我们转换了字符串"-18446744073709551616"。结论:

errno:  34
ullval: 18446744073709551615

我们也得到了预期的输出。

  1. "-18446744073709551616"减号已从行中删除。
  2. 字符串"18446744073709551616" 中的数字不能用type表示unsigned long long。因此,我们改变errno,并返回ULLONG_MAX。

示例#3

errno = 0;
long long llval = std::strtoll("-9223372036854775808", nullptr, 10);
cout << "errno: " << errno  << endl;
cout << "llval: " << llval  << endl;

结论:

errno: 0
llval: -9223372036854775808

现在问题出现了。

  1. "-9223372036854775808"减号已从行中删除。
  2. 字符串"9223372036854775808" 中的数字不能用type表示long long。因此,有必要安装errno并返回LLONG_MIN。

为什么函数std::strtoll()返回LLONG_MIN但没有设置errno?(代码示例的链接:g++,clang)


此外,Visual Studio 2010 中的以下代码(我现在手头没有更新的代码):

errno = 0;
unsigned long ulval = std::strtoul("-4294967296", nullptr, 10);
cout << "errno: " << errno   << endl;
cout << "ulval: " << ulval   << endl;

产生以下输出:

errno: 34
ulval: 1

"-4294967296"丢弃减号后字符串中的数字不能用类型表示unsigned long,因此必须设置errno(发生),返回值ULONG_MAX,但函数返回1。


strtol()根据语言标准,通过函数/strtoll()及其无符号对应项将字符串转换为整数的算法是什么。我试图理解标准中的内容并没有成功。


嗯,有人投票结束了这个问题,原因是“由错字引起的问题或不可重现的问题”。

可能值得关闭,但首先,如果“问题没有重现”,那么我希望看到一个编译器示例,在执行代码后std::strtoll("-9223372036854775808", nullptr, 10),它将设置errno为非零值。

如果errno不应该设置它,那么我很乐意阅读为什么不应该设置它的解释(当然,参考标准)。

c++
  • 1 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-07-21 06:20:01 +0000 UTC

链接和临时对象

  • 2

有这个代码:

#include <iostream>

void test(const int& val)
{
    const_cast<int&>(val) = 42;   
}

int main()
{
    int   val1 = 0, val2 = 0, val3 = 0;

    test(val1);
    test(val2 + 0);
    test(static_cast<int>(val3)); //Интересная строка;

    std::cout << val1 << " " << val2 << " " << val3 << std::endl;

    return 0;
}

海合会输出:

42 0 0

MS Visual Studio 输出:

42 0 42

谁是对的,为什么?

c++
  • 1 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-03-09 04:42:26 +0000 UTC

溢出二维数组的子数组

  • 2

根据C++ 语言标准[expr.add], 7.6.6/4,如果我们有一个指向某个元素数组p的i第-个元素的指针n,并且有一个整数值j,那么该指针p + j指向i + j-th 元素 if if 0 <= i + j <= n; 否则,程序的行为是未定义的。

所以下面代码的行为是未定义的:

int arr[2];
int *pi = arr + 3; //UB

但是,如果我们“超越”二维数组的子数组会发生什么?例子:

int arr[2][2];
int (*p)[2] = arr;
int *pi = *p;
pi = pi + 3; //UB?

指针p指向数组的第一个元素arr,即 到类型为 的两个元素的数组int。指针pi指向类型为 的两个元素组成的数组的第一个元素int。在表达式中,尽管我们仍在数组内部,但pi + 3我们走出了两个 type 元素的数组。intarr

问题 1.pi + 3从语言标准的角度来看,表达是否是未定义的行为?

问题 2. 以下代码是否正确:

int arr2[1];
int *pi2 = arr2 + 1;
*pi2; //OK?

我对字符串感兴趣*pi2;。

c++
  • 3 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-12-07 04:19:01 +0000 UTC

C++中的赋值运算符

  • 7

语言标准中对赋值运算符的描述有几点我不清楚,我想澄清一下。

n4659,8.18/1:

[...] 在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。右操作数在左操作数之前排序。对于不确定顺序的函数调用,复合赋值的操作是单次求值。[注意:因此,函数调用不应干预左值到右值的转换以及与任何单个复合赋值运算符相关的副作用。——尾注]

问题 1. 什么是值计算,它是按照以下代码中左右操作数的标准执行的:

a = 1;

问题 2. 函数调用的不确定顺序是什么意思?我想看一个在同一个表达式中涉及赋值和函数调用的示例,其中函数调用相对于某物是无限排序的。

n4659, 8.18/8:

如果存储在一个对象中的值是通过另一个对象读取的,该对象以任何方式与第一个对象的存储重叠,那么重叠应该是精确的,并且两个对象应该具有相同的类型,否则行为是未定义的。[注:此限制适用于赋值操作的左右关系;它不是关于分配的目标通常如何别名的声明。见 6.10。——尾注]

问题 3. 我想看一个符合上述引用描述的例子。


除了问题 1。

也许将问题如下提出更有意义:从语言标准的角度来看,值计算是否总是在赋值运算符的操作数上执行?如果没有,什么时候完成,什么时候没有?

重点是这个。这个问题的第一句话说赋值发生在两个操作数的值计算发生之后。它还说右操作数在左操作数之前排序(即,与右操作数相关的值计算 + 副作用将发生在与左操作数相关的值计算 + 副作用之前)。

因此,如果在赋值运算符中,左操作数的值计算总是发生在实际赋值之前,那么右操作数总是在赋值之前排序。

c++
  • 2 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-12-07 03:38:32 +0000 UTC

在 Visual Studio 中将函数指针隐式转换为 void *

  • 3

有这个代码:

    #include <iostream>
    using namespace std;

    int func()
    {
        cout << "func" << endl;
        return 0;
    }

    int main()
    {
        void * p;

        p = func;
        cout << p << endl;
        cout << func << endl;

        return 0;
    }

在 Visual Studio 2010 中,此代码编译良好并在两种情况下都输出一些地址。

问题 1. 是否存在允许您将函数(指向函数的指针?)转换为类型的隐式转换void *?

问题 2. 为什么在将函数作为参数传递给重载的 operator时,<<编译器会再次将函数(指向函数的指针?)转换为 type void *,而不是转换为bool?毕竟,有一个隐式转换允许您将指针转换为类型bool。

c++
  • 1 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-10-03 01:10:33 +0000 UTC

在 C++ 中将一元减号应用于无符号值

  • 8

语言标准一再提到对无符号整数的运算是模执行的2^n,其中n是表示无符号整数值所涉及的位数。

让我们有这个代码:

    unsigned char a = 1;
    a = -a;

而且,让unsigned char八位,但int十六位。

我已经认为表达式-a要么立即转换为类型的值unsigned char,等于255; 要么a扩展为int,然后这个int接受一个值-1,最后-1转换为类型unsigned char等于的值255。然而,事实证明,该标准指定了一种特殊的、相当奇怪的方法来计算无符号值的一元减号。

这是该文件第 8.3.1/8 段的引述:

一元 - 运算符的操作数应具有算术或无范围枚举类型,结果是其操作数的否定。对整数或枚举操作数执行整数提升。无符号量的负数是通过从 中减去其值来计算的2^n,其中n是提升操作数中的位数。结果的类型是提升的操作数的类型。

如果我理解正确写的内容,那么-a上面示例中的表达式的值等于 value 2^n - 1,它n等于扩展操作数中的位数。那些。2^n - 1 == 2^16 - 1 == 65536 - 1 == 65535. 但是给定的值不能用 16 位表示int,这意味着尝试计算-a会导致未定义的行为。

问题是:一元减法可以像上面写的那样“起作用”吗?如果是这样,为什么标准会为无符号值定义这种奇怪的一元减法行为?


如果你这样写也很奇怪:

    unsigned char a = 1;
    a = 0 - a;

那么它似乎不会导致未定义的行为。因为它0是 type int,所以变量被a扩展为int,计算差值0-1,并且 type 的结果值被int安全地截断256为255。

c++
  • 2 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-09-05 07:03:17 +0000 UTC

在 C++ 中表示有符号整数的方法

  • 19

语言标准规定整数类型可以用以下三种方式之一表示:

  • 2的补码,
  • 1的补码,
  • 有符号值。

在这方面,出现了几个问题:

  1. 现在除了2 的补码以外的整数表示吗?

  2. 该标准是否允许在同一实现中对整数类型进行不同的表示?例如,什么char是2 的补码和1int的补码?

  3. 整数的不同表示如何与按位运算一致?例如,让我们有这样的代码:

    unsigned char a = 1;    
    a = ~a;
    

并让一些实现使用 8 位char和 16位,并使用1 的补码int来表示有符号整数,即 我们在反向代码中存储负值。我的印象是可以进行以下转换来计算变量的值:a

  1. 该变量将a进行整数扩展为int,因为根据标准,位否定操作数可以扩展。那些。位集00000001转换为00000000 00000001.
  2. 将发生位反转,即 扩展值变为11111111 11111110。
  3. 此位序列将被解释为有符号整数,因为根据标准,位否定的结果是扩展操作数类型。反向代码中的这个位序列表示一个整数-1。
  4. 整数-1将被转换为无符号整数unsigned char模256。那些。该变量a将采用值255,该值由以下位序列编码:11111111。这有点奇怪,因为通过按位否定位序列00000001,我希望得到11111110,而不是11111111。

这种位否定是标准允许的,还是上面的例子根本错误?

c++
  • 1 个回答
  • 10 Views
Martin Hope
wololo
Asked: 2020-08-09 22:26:23 +0000 UTC

在 C++ 中将 double 转换为浮点数

  • 6

让类型变量double转换为类型变量float。如果变量double包含一个值NaN,则将其转换为NaN。如果变量double包含一个值Inf,则将其转换为Inf。如果变量double包含一个值-1e+50,则将其转换为-Inf。

这种行为是由 C++ 标准保证的,还是IEEE 754保证的?或者它是实现定义的行为,还是通常未定义的行为,一般来说不值得指望-1e+50转换-Inf为什么?

c++
  • 1 个回答
  • 10 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5