This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/EK-TM4C1294XL:根据 EEPROM 中存储的值设置 IP 地址

Guru**** 2460850 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/651170/rtos-ek-tm4c1294xl-setting-an-ip-address-from-a-stored-value-in-the-eeprom

器件型号:EK-TM4C1294XL

工具/软件:TI-RTOS

希望这是一个简单的问题。  我尝试使用静态 IP 地址、但微控制器需要从 EEPROM 读取该地址。  当我尝试运行程序时,固件会在我将*LocalIPAddr 设置为包含 IP 地址的字符串后崩溃。  崩溃意味着它会编译和运行,但在运行时会出现问题,并使用 exit.c 中的 abort 函数终止。   

具体而言,我使用此代码将 EEPROM 中的值转换为字符串,并将*LocalIPAddr 设置为该字符串。  在最后一行代码中,如果我将*addresssString 替换为"192.168.3.5",它就会起作用,因此我确信我只是在处理指针时犯了一个愚蠢的错误,或者我在缺少的格式中做了一些错误。

空 readIPAddr (空)

uint32_t temp[1];
字符地址[4];
字符地址 String[17];

EEPROMRead (temp、100、sizeof (temp));
地址[0]= temp[0]和255;
地址[1]=(temp[0]>> 8)和255;
地址[2]=(temp[0]>> 16)和255;
地址[3]=(temp[0]>> 24)和255;
sprintf (address 字符串、"%U.%U.%u"、address[3]、address[2]、address[1]、address[0]);
*LocalIPAddr =*addresssString;
TEMP[0]= TEMP[0];

readIPAddr 由堆栈线程开始挂钩调用、位于 TI-RTOS >产品> NDK >网络>堆栈挂钩函数下

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    首先、请使用粘贴代码( 图标)。 如果您不这样做、格式将会丢失。

    现在谈谈物质的肉质。

    这是奇怪的,不是错误的,但无疑是奇怪的,它会导致你在以后的时候误入歧途。

    [引用 user="Thodden Spaporetti26"] uint32_t temp[1];[/quot]

    这应该是显式无符号字符或 uint8_t 正如所写的那样、它可能是有符号或无符号(取决于编译器)、从而导致有趣的符号扩展问题

    [引用 user="Thodden Spaporetti26"]字符地址[4];[/quot]

    sizeof (temp)是指向 uint32_t 的指针的大小、而不是 uint32_t 的大小 后者就是您想要的。 幸运的是、它们恰好是相同的。

    [引用 user="Thodden Spaporetti26"] EEPROMRead (temp、100、sizeof (temp));[/quot]

    在这里、您可以混合有符号和无符号整数。

    [引用 user="Thodden Spaporetti26"]地址[0]= temp[0]和255;
    地址[1]=(temp[0]>> 8)和255;
    地址[2]=(temp[0]>> 16)和255;
    地址[3]=(temp[0]>> 24)和255;[/报价]

    在这里、您使用 sprint (不是一个好主意)并传递未知符号值、我认为它应该转换为有符号整数。

    [引用 user="Thodden Spaporetti26"] sprintf (address sString、"%U.%U.%u"、address[3]、address[2]、address[1]、address[0]);

    这可能是导致您的问题的原因。 您似乎希望复制字符串。 这不是您正在做的、请仔细看一下。

    [引用用户="Thodden Scaporetti26"]*LocalIPAddr =*地址字符串;

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我乐于接受有关更好编码方法的建议、因为编码不是我的主要工作要求、甚至不是次要工作要求、所以我不会每天进行编程。  不过、我会说为什么我做出了选择。  

    我直接从 Tiva C 用户外设驱动程序库用户指南中给出的示例中获取了此代码。  使用单个变量读取页时遇到一些问题(word?) 使用该命令从 EEPROM 发送数据。  因此、我只需设置一个元素数组。  该示例专门使用 sizeof ()获取多元素数组的大小,我的代码数组是一个元素。  就我所知、sizeof (array)返回数组的大小、而不是数组指针的大小。

    在这种情况下、我可以轻松地放置4、并节省一些处理器时间、但由于我没有按处理器使用、我更喜欢在任何地方使用相同的方法。   

     [引用用户="Robert Adsett"]

    sizeof (temp)是指向 uint32_t 的指针的大小、而不是 uint32_t 的大小 后者就是您想要的。 幸运的是、它们恰好是相同的。

    Thodden Scaporetti26.
    EEPROMRead (temp、100、sizeof (temp));

    [/报价]

    传统上、char 变量既不是有符号变量、也不是无符号变量、除非您指定它是我遇到的 C 版本、其中默认值是一个或另一个版本。  在本例中、它对我使用它的方式没有影响、但出于安全考虑、我可能应该强制它在声明中无符号。

    [引用用户="Robert Adsett"]

    在这里、您可以混合有符号和无符号整数。

    Thodden Scaporetti26.
    地址[0]= temp[0]和255;
    地址[1]=(temp[0]>> 8)和255;
    地址[2]=(temp[0]>> 16)和255;
    地址[3]=(temp[0]>> 24)和255;

    [/报价]

    我特别需要一个无符号值、因为 IP 地址是无符号的、%u 将自动将字符变量解释为无符号。  但是、使用 sprintf 是我身边的一个快捷方式、因为这是我知道的将多个数字转换为单个字符串的最简单方法。  如果有更好的方法、我愿意接受建议。

    [引用用户="Robert Adsett"]

    在这里、您使用 sprint (不是一个好主意)并传递未知符号值、我认为它应该转换为有符号整数。

    Thodden Scaporetti26.
    sprintf (address 字符串、"%U.%U.%u"、address[3]、address[2]、address[1]、address[0]);

    [/报价]

    这是我确定问题所在的地方。  这只是我最后一次尝试使其正常工作、我经历了几次尝试复制字符串的迭代。  这是唯一一个在函数退出之前未使代码崩溃的代码、其余部分在运行代码行后直接崩溃。  我还尝试了 strcpy(),并尝试使用以下代码手动复制字符串:

    addressPointer = addresssString;
    I = 0;
    while (* address Pointer!='\0')
    LocalIPAddr[i++]=*地址 Pointer++; 

    [引用用户="Robert Adsett"]

    这可能是导致您的问题的原因。 您似乎希望复制字符串。 这不是您正在做的、请仔细看一下

    Thodden Scaporetti26.
    *LocalIPAddr =*addresssString;

    [/报价]

    因此、无论我如何复制地址字符串、我的问题仍然存在。  出于测试目的、我还尝试 了 LocalIPAddr[0]='1'; 只需更改 LocalIPAddr 中的第一个字符、即使'1'是当前存储在其中的同一个字符、它也会崩溃。  我猜 LocalIPAddr 有一些我不知道的特别之处。  或者、我可能忘记了在 C 语言中操作字符串的一些东西   

    如果我将函数中的字符串复制方法替换为 LocalIPAddr  ="192.168.6.2"、   则可以正常工作。  遗憾的是、它无法解决问题、因为这意味着 IP 地址是硬编码的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Thodden Spaporetti26">使用单个变量读取页面(word?)时遇到一些问题 使用该命令从 EEPROM 发送数据。  [/报价]

    它们是什么?

    [引用 user="Thodden Spaporetti26"] 该示例专门使用 sizeof ()来获取多元素数组的大小,我的代码数组是一个元素。  据我所知、sizeof (array)返回数组的大小、而不是数组指针的大小。

    是的、你说得对、我想的是一个不同的案例。

    [引用 user="Thodden Scaporetti26"]在本例中,我可以轻松地将4替换为4,从而节省一些处理器时间

    不会、所花费的处理器时间是相同的。 这是在编译时确定的。

    [引用 user="Thodden Spaporetti26"]传统上,char 变量既不是有符号变量,也不是无符号变量

    再说一次、不 它是特定于编译器的。 事实上、编译器必须在文档中指定它是有符号的还是无符号的。 用户也不应依赖于表示形式。 如果使用 char 表示一个小数、则应显式选择有符号或无符号。 如果使用 char 表示可见字符、则应使用 plain char。

    [引用用户="Thodden Scaporetti26"]

    我特别需要一个无符号值、因为 IP 地址是无符号的、%u 将自动将字符变量解释为无符号。  但是、使用 sprintf 是我身边的一个快捷方式、因为这是我知道的将多个数字转换为单个字符串的最简单方法。  如果有更好的方法、我愿意接受建议。

    Robert Adsett

    在这里、您使用 sprint (不是一个好主意)并传递未知符号值、我认为它应该转换为有符号整数。

    Thodden Scaporetti26.
    sprintf (address 字符串、"%U.%U.%u"、address[3]、address[2]、address[1]、address[0]);

    [/报价]

    我在这里有符号/无符号数表示地址参数被隐式转换为 INT。 这种转换可能会带来麻烦、因为我怀疑超过少数人(可能是编译器或测试套件的所有作者)完全内部存在的规则。

    sprintf (Damn、我认为原始文件是从 sprintf 自动重传到 sprint 的) 从几个角度来看是危险的

    1. 它使用大量堆栈、在某些情况下还使用堆。 这在通常分配了小型堆栈的嵌入式应用和嵌入式演示中尤其成问题。
    2. 它没有溢出保护
    3. 它使用了复杂的语法,尽管经常使用的用户会记住它
    4. 我需要大量的代码空间。

    我没有看到有人提出嵌入式应用中不应禁止这种行为的令人信服的理由。 就替代品而言,它更简单、更小、更安全。

    [引用用户="Thodden Scaporetti26"]

    Robert Adsett

    这可能是导致您的问题的原因。 您似乎希望复制字符串。 这不是您正在做的、请仔细看一下

    Thodden Scaporetti26.
    *LocalIPAddr =*addresssString;

    [/报价]

    好的、这个和

    [引用用户="Thodden Spaporetti26"] LocalIPAddr ="192.168.6.2'; [/quot]

    这是完全完全不同的。

    一个复制(或尝试)一个字符而不是另一个字符。 当要覆盖的字符位于 ROM 中时会发生什么情况?

    另一个将指向字符串的指针替换为指向不同字符串的指针。

    不同类型和不同的存储器位置。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [quote user="Thodden Spaporetti26">和%u 将自动将字符变量解释为无符号变量。  [/报价]

    一个细微的注意事项、我 认为我没有得到适当的解决。 如果对* printf 系列有任何介绍、则不多。

    %u 将在传递的变量位置将相关的有符号整数解释为有符号整数。 这是一个微妙的差异、但它可能很重要、因为它是不寻常的情况。 它还指出,*printf 系列容易受到传递的错误大小类型的影响。 如果类型大小不匹配、不仅会"打印"错误的结果、而且之后的任何结果也会出现、实际上您可能会遇到处理器故障。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Robert Adsett"]

    Thodden Scaporetti26.
    传统上、char 变量既不是有符号变量、也不是无符号变量

    [/报价]

    是的、这意味着'c'或任何其他字符常量具有定义的符号。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Thodden Scaporetti26"]

    Robert Adsett

    在这里、您可以混合有符号和无符号整数。

    Thodden Scaporetti26.
    地址[0]= temp[0]和255;
    地址[1]=(temp[0]>> 8)和255;
    地址[2]=(temp[0]>> 16)和255;
    地址[3]=(temp[0]>> 24)和255;

    [/报价]

    我想您可能错过了我在这里的观点。

    如果不仔细看、您能告诉我在这个代码块中进行的各种隐式转换、顺序是什么?

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我只需回复这个问题就可以解决所有问题、包括后面出现的一些回答。

    我明白这些是完全不同的。 正如我提到过的、这是我的最后一次迭代、我基本上只是在墙上扔代码来看看卡住了什么。  我尝试了标准复制方法、甚至只是简单地更改了 LocalIPAddr 中的单个字符、IE LocalIPAddr[0]='1'。  我还尝试了*本地 IPAddr =*本地 IPAddr;  这应该不执行任何操作,但所有这些都导致了相同的问题。  据我所知、分配给 LocalIPAddr 的存储器会阻止个别更改、而尝试更改它的行为会导致崩溃。  但是、指针本身未被锁定、这导致我尝试我发布的代码、以及它在函数末尾而不是在函数中间崩溃的原因。

    这次讨论确实让我找出了一种变通办法。  我对它不满意、但它确实起作用。  我为新的 IP 地址创建全局 char 数组(因此不会将其清除)、然后将 LocalIPAddr 指向新数组。  这意味着任何最初分配给 LocalIPAddr 的存储器块都无法回收。   

    [引用用户="Robert Adsett"]

    Thodden Scaporetti26.
    *LocalIPAddr =*addresssString;

    好的、这个和

    Thodden Scaporetti26.
    LocalIPAddr ="192.168.6.2";  

    这是完全完全不同的。

    [/报价]

    至于 EEPROMread 函数的问题、我可能只是使用了无符号 int 而不是 uint32_t、而是将其切换为数组。  在我看来、我可能只是通过发送变量而不是指向变量的指针来犯了一个简单的错误。  老实说、我不记得、因为我几周前就解决了这个问题、并以这种方式解决了这个问题。  至于 sizeof(),我没有意识到编译器将其用作常量。  这是一个好知识。

    使用 itoa()是一个很好的建议,但它包含在哪个库中?  它不在 CCSV stdlib.h 中、其中存在 atoi、strtol 和类似函数(I 已检查)。  我想没关系、我可以自己构建自己的、我很懒。  不过、我一直在使用 vsprintf 格式化任何需要通过以太网发送的字符串。  我已经确保堆栈和堆足够大、这样就不需要高速性能、尽管我仍然需要更好的方法来设置和生成具有多个变量的输出字符串。   

    [引用用户="Robert Adsett"]

    地址[0]= temp[0]和255;
    地址[1]=(temp[0]>> 8)和255;
    地址[2]=(temp[0]>> 16)和255;
    地址[3]=(temp[0]>> 24)和255;

    我想您可能错过了我在这里的观点。

    如果不仔细看、您能告诉我在这个代码块中进行的各种隐式转换、顺序是什么?

    [/报价]

    我可能会误解您对我的要求。  但是、当设置 char = int 时、char 变量设置为整数的最低有效字节、这是发生的唯一隐式转换、也是最后发生的转换。  由于我在等式部分中只使用一个变量、它是一个32位整数、因此数学和逻辑完全作为一个整数完成、因此这里没有隐式转换、它将所有内容视为32位值。 由于这种情况、技术 上的地址[0]= temp[0]和255;等效于地址[0]= temp[0];   

    对于:  address[1]=(temp[0]>> 8)和255; 8的右位移首先发生、将第二个最高有效字节移入最低有效字节、然后按位&发生、最后将最低有效字节放入 address[1]。  同样、在技术上不需要使用& 255、因为只有最低有效字节存储在 char 中。   如果等式不那么简单、我怀疑我可以在不查询运算顺序的情况下回答、例如、int 除以浮点。

    如果一个 char 被视为有符号数、放入 char 的数字将为负、是最高有效位为1、然后它会将该值解释为二进制补码格式的负值。  无论整数是有符号的、无符号的、还是原始数字是负数还是正数、都将执行此操作。  然而、CCSV 针对所有意图和目的将一个 char 视为无符号。  我确实同意、如果代码被移植到将 char 视为已签名的编译器、我应该指定它是无符号的、只是出于尽职调查。   

    但是、本次讨论中没有一个涉及潜在问题、尽管我确实很感激、因为正如我所说的、我并不主要是一名编码器、良好做法始终是需要了解的重要因素。  正如我一开始说的、我发现了一个解决方法、尽管它没有回答我的问题、即为什么我无法更改 LocalIPAddr 指向的值。   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Thodden、我想您对 C 语言中的指针缺乏了解、而这个论坛更专注于硬件。

    尝试教程: www.cprogramming.com/.../lesson6.html 指针需要比正常 C 语法更好的理解。 IF 语句、运算符和函数都易于理解。

    如果您了解自己在做什么、您会对您发布的代码感到羞耻。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Thodden Scaporetti26"]为了进行测试,我还尝试了*本地 IPAddr =*本地 IPAddr;  该操作不执行任何操作,[/引用]

    不是真的。 给定足够高级的编译器、该编译器可能会转换为 NOP、但不一定会转换为 NOP。 这取决于 LocalIPAddr 被声明为什么。

    但是、我怀疑大多数编译器不会将其优化掉。 在这种情况下、给出了的初始声明

    char *LocalIPAddr ="192.168.1.1"; 

    和后续任务

    *LocalIPAddr =*LocalIPAddr; 

    写入的存储器位置是什么(即、写入的存储器类型是什么)?

    请注意、C 标准明确禁止此分配。

    [引用 user="Thodden Spaporetti26">此讨论确实让我确定了一种权变措施。  我对它不满意、但它确实起作用。  我为新的 IP 地址创建全局 char 数组(因此不会将其清除)、然后将 LocalIPAddr 指向新数组。  这意味着任何最初分配给 LocalIPAddr 的存储器块都无法回收。   [/报价]

    我没有 LocalIPAddr 的声明或声明上的任何文档(您应该有这些文档)、但如果需要、我也不会感到惊讶。

    [引用 user="Thodden Scaporetti26">我可能会误解您对我的要求。  但是、当设置 char = int 时、char 变量设置为整数的最低有效字节、这是发生的唯一隐式转换、也是最后发生的转换。

    不会、该代码块的每一行都有多个隐式转换。

    [引用 user="Thodden Scaporetti26"]我找到了一个解决方法,尽管它没有回答我的问题,即为什么我无法更改 LocalIPAddr 指向的值。  [/报价]

    您还没有向我们显示 LocalIPAddr 被声明为什么。

    [引用 user="Thodden Scaporetti26"]我不是主要编码者,良好做法始终是需要了解的重要因素。

    有一个原因我一直建议使用 PC-Lint

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Thodden Spaporetti26"]对于我的 EEPROMread 函数问题,我可能只是使用了无符号整型值而不是 uint32_t,

    这很不可能成为根本原因。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉、当我说它不应该做任何事情时、我意味着值应该完全相同。  它不应导致崩溃、因为该值设置不正确。  它被设置为自己、因此不应创建致命错误、但确实如此。

    [引用用户="Robert Adsett"]

    Thodden Scaporetti26.
    为了进行测试,我还尝试了*LocalIPAddr =*LocalIPAddr;  该操作不执行任何操作,

    不是真的。 给定足够高级的编译器、该编译器可能会转换为 NOP、但不一定会转换为 NOP。 这取决于 LocalIPAddr 被声明为什么。

    [/报价]

    [引用 user="Robert Adsett"]您还没有向我们显示 LocalIPAddr 声明为什么。

    这可能是我问题的根源。  LocalIPAddr 通过 TI-RTOS 文件声明。  我在"IP-General Settings"下的 cfg 文件中设置静态 IP 地址、并使用这些设置自动创建自己的文件。  我不熟悉 Code Composure Studio、但如果我使用 F3打开声明、我会看到:

    char *LocalIPAddr ="192.168.1.2"; 

    它是我输入的初始静态 IP 地址。  我完全了解该变量的唯一原因是、我关注了一个讨论该变量的旧论坛主题。  为了确保我能够访问 LocalIPAddr、我将在代码顶部声明:

    extern char * LocalIPAddr; 

    我完全可能缺少一些明显的东西。  在回复之前、我花了一些时间对此进行了调查、如果我尝试写入使用声明的字符串中的任何位置、程序似乎会崩溃

    char *字符串="xyz";
    char temp; 

    那么、如果我这么做

    temp = string[1]; 

    温度设置为"y"、但当我尝试反向时程序会崩溃、  

    string[1]= temp; 

    只需声明一个 char 数组即可完美运行、同时还可以声明设置为 char 数组的指针。  通常、我只需为 LocalIPAddr 创建一个字符阵列就可以解决此问题、但我无法控制 LocalIPAddr 的声明方式、因为它是由 TI-RTOS 端创建的。  因此、忽略我们一直讨论的任何其他明显的非标准代码问题、这是我的问题所在的根源。  正如我提到的、我确实有一项可行的工作、但我想知道导致这一问题的原因。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这更多地是 TI-RTOS 问题、它现在似乎与硬件论坛结合了。  但是、我很遗憾、我在当天发布了我用于故障排除和确定问题发生位置的最后一个代码。  工作日晚了,显然有损于对问题的了解。  你是对的、我不应该发布该特定行、因为这是错误的、相当尴尬。  但是,它确实提供了有用的信息。  我将列出我尝试过的代码链、我应该首先完成这些代码链。  我尝试的第一件事是

    sprintf (LocalIPAddr、"%U.%U.%U.%u"、address[3]、address[2]、address[1]、address[0]); 

    由于程序在该行上崩溃、我创建了自己的字符串、addresssString 、并尝试 strcpy (LocalIPAddr、addressString); 同样、 即使我尝试了硬编码字符串、它也会在函数中崩溃。   接下来、我尝试使用以下代码手动执行该操作:

    addressPointer = addressString;
    i = 0;
    while (* addressPointer!='\0')
    LocalIPAddr[i++]=*地址 Pointer++; 

    我认为这是相当标准的,但当它运行 LocalIPAddr[i++]=*地址点++行时,它也崩溃了; 现在可以说我在处理指针和字符串方面很怀疑,但我相信这是一种正确的处理方法。  我还尝试了该行的几种变体。  因此、我尝试通过几种方法简单地更改单个字符:

    *LocalIPAddr ='1'; 

    LocalIPAddr[1]='9';

    这两种情况都立即崩溃。  这就是为什么我尝试了你正确地认为例外的更令人发指的代码、它直到函数结束、而不是直接跟踪代码行后才崩溃。  由于这是一个不同的结果、它为我提供了一个有关我今天找到的权变措施的线索(创建一个新字符串、而是将 LocalIPAddr 指向那个字符串。)   

    现在、问题的一部分是 LocalIPAddr 是由 TI-RTOS 创建的指针变量、因此我不知道它是如何声明的、而不是它是一个指针。  在编写此函数并读取另一个响应时、我找到了 RTOS 端创建的声明。   

    char *LocalIPAddr ="192.168.1.2"; 

    现在我已经完成了一些进一步的测试、您可以在我的另一篇文章中阅读它。  但简短的版本是、如果我尝试写入该方法中的特定位置、则在该方法中声明任何字符串都会导致崩溃。   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Thodden Scaporetti26"]

    这可能是我问题的根源。  LocalIPAddr 通过 TI-RTOS 文件声明。  我在"IP-General Settings"下的 cfg 文件中设置静态 IP 地址、并使用这些设置自动创建自己的文件。  我不熟悉 Code Composure Studio、但如果我使用 F3打开声明、我会看到:

    char *LocalIPAddr ="192.168.1.2"; 

    [/报价]

    我认为这是 RTOS 中的一个错误、应该将其声明为

    const char * LocalIPAddr ="192.168.1.2"; 

    我认为以后会很明显的原因。

    [引用用户="Thodden Scaporetti26"]

    char *字符串="xyz";
    char temp; 

    那么、如果我这么做

    temp = string[1]; 

    温度设置为"y"、但当我尝试反向时程序会崩溃、  

    string[1]= temp; 

    只需声明一个 char 数组即可完美运行、同时还可以声明设置为 char 数组的指针。  通常、我只需为 LocalIPAddr 创建一个字符阵列就可以解决此问题、但我无法控制 LocalIPAddr 的声明方式 、因为它是由 TI-RTOS 端创建的。  因此、忽略我们一直讨论的任何其他明显的非标准代码问题、这是我的问题所在的根源。  正如我提到的、我确实有一项可行的工作、但我想知道导致这一问题的原因。

    [/报价]

    是的,完全符合预期*。

    思考正在发生的情况。

    1. 字符串"xyz"将存储在 ROM 中(微闪存)
    2. 因此、字符串[1]指的是闪存中特定位置的"x"
    3. 因此、string[1]= temp 尝试覆盖闪存中的"x"
      1. 最好的情况是、这不起任何作用
      2. 最坏情况是由于写入只读存储器而导致的内核故障。

    C 标准明确禁止第二个序列**。

    Robert

    *在内存受保护的环境中。 如果程序存储在易失性存储器中,则最终可能会修改常量字符串***。

    **第一个 C 标准决定的字符串常量将具有一种字符*。 这样做是为了保持向后兼容性、不要求现有程序更新所有字符串赋值以显式识别 const。 我不确定这是正确的方法、因为它使这种情况更难诊断、但鉴于 现有代码的数量、这是可以理解的、可能是合理的。  诸如 PC-Lint 等静态分析程序确实认识到了这一缺陷、并且可以帮助诊断这种情况。 实际字符串应声明为 const char *字符串(指向常量 char 的指针)

    ***我听说 早期的 Fortran 程序出现了这种问题。 如果您为数字指定了一个值,即42=3*2,则程序中对42的任何其他引用现在将具有值6

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Thodden Scaporetti26"]

    很抱歉、当我说它不应该做任何事情时、我意味着值应该完全相同。  它不应导致崩溃、因为该值设置不正确。  它被设置为自己、因此不应创建致命错误、但确实如此。

    Robert Adsett
    Thodden Scaporetti26.
    为了进行测试,我还尝试了*LocalIPAddr =*LocalIPAddr;  该操作不执行任何操作,

    不是真的。 给定足够高级的编译器、该编译器可能会转换为 NOP、但不一定会转换为 NOP。 这取决于 LocalIPAddr 被声明为什么。

    [/报价]

    是的、它可能会导致崩溃。 只是因为最终结果显然与开始结果相同并不意味着什么都没有发生。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Robert Adsett"]我认为这是 RTOS 中的一个错误,应该声明为

    它不是。 对于指向非常量字符的指针 来实际存储常量字符地址而言、这是非常好的。 反向是不正确的、会向您发出警告。

    //
    此处没有什么问题 char * strPtr ="Hey gers";
    
    //编译器将提供警告
    char c ='c';
    const char * constPtr =&c; 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Robert Adsett"]

    是的,完全符合预期*。

    思考正在发生的情况。

    1. 字符串"xyz"将存储在 ROM 中(微闪存)
    2. 因此、字符串[1]指的是闪存中特定位置的"x"
    3. 因此、string[1]= temp 尝试覆盖闪存中的"x"
      1. 最好的情况是、这不起任何作用
      2. 最坏情况是由于写入只读存储器而导致的内核故障。

    C 标准明确禁止第二个序列**。

    Robert

    [/报价]

    这可能是我产生困惑的原因。  以前我只使用了用于 PIC 微控制器的 C 编译器、它们的 C 编译器将 char *指针="xyz"视为与 char * string[3]="xyz"相同。  这可能不是标准、但这是我所熟悉的。

    无论如何,这是一个信息量很大的问题,让我知道我需要走什么方向。  感谢您的帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Thodden Scaporetti26"]

    这可能是我产生困惑的原因。  以前我只使用了 PIC 微控制器的 C 编译器

    [/报价]

    我怀疑 PICS 的任何 C 编译器是否符合标准、尽管应该可以构建符合标准的编译器。 如果您通过编程 PIC 学习 C 语言、我怀疑这不是唯一被引导的地方

    [引用 user="Thodden Spaporetti26"] C 编译器对 char *指针="xyz"的处理方式与 char * string[3]="xyz"相同。  这可能不是标准、但这是我所熟悉的。

    完全允许它们生成对它们进行完全相同处理的代码、不允许假设您可以写入字符串文字。 事实上、该标准 禁止您这样做。 从逻辑上讲、它也是一个错误、因此它不应该是您想要做的事情。

    [引用 user="Thodden Scaporetti26"]让我知道我需要朝什么方向前进。

    您已经确定了(并给自己一个在该过程中解决的问题;)。 您需要存储 IP 地址字符串、以使其不会被覆盖、并使用字符串的地址更新地址 LocalIPAddr。

    Robert

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Peter Borenstein"]

    Robert Adsett
    我认为这是 RTOS 中的一个错误、应该将其声明为
    //
    此处没有什么问题 char * strPtr ="Hey gers";
    
    //编译器将提供警告
    char c ='c';
    const char * constPtr =&c; 

    [/报价]

    我相信您误解了我认为这是一个错误的原因

    [引用用户="Robert Adsett"]

    我认为这是 RTOS 中的一个错误、应该将其声明为

    const char * LocalIPAddr ="192.168.1.2"; 

    我认为以后会很明显的原因。

    [/报价]

    请注意、我的声明与您的第二个声明不同。 虽然区别很重要、但我认为它不会影响您的异议。 很显然、我的原因并不明显、让我展开讨论。 给定在 RTOS 中声明的以下内容(注意、这会为指向非 const char 的指针分配一个指向字面量的指针)

    char *LocalIPAddr ="192.168.1.2"; 

    我认为有两种可能性

    1. LocalIPAddr 应由 RTOS 本身或应用程序写入(正如声明所暗示的那样)。
      1. 那么、字符串字面量的赋值显然是一个错误。
    2. LocalIPAddr 不应由 RTOS 写入
      1. 在这种情况下、字符串文字分配是正确的
      2. 在这种情况下、声明也应与我所给出的声明相同、 原因有很多
        1. 以表明 RTOS 不会对其进行写入
        2. 防止 RTOS 用户尝试修改 LocalIPAddr 指向的内容并成功编译。 如果已经这样做、则整个线程将不是必需的。

    在这两种情况下、这都属于错误。

    以直接解决您的问题。 编译器不会为以下内容生成警告或错误的事实也是如此

    [引用用户="Peter Borenstein"]//这里没有什么问题 char * strPtr ="Hey Guies\n";[/quot]

    这并不意味着它没有错误、同样也不遵循以下警告

    [引用 user="Peter Borenstein"]//编译器将给出警告 char c ='c';const char * constPtr =&c;[/quot]

    不一定表示代码中存在错误(尽管应仔细检查并正确注释)。 我可以考虑该结构的其他有效用途、尤其是与易失性结合使用。 是的、您应该避免编译器警告、但不要以 错误为代价。 这种特殊的警告行为源于 C 标准委员会的决定、即使字符串文字作为常量运行、以便遵循早期的实践并遵循构造的逻辑含义、但不使字符串文字具有常量类型。 如果它们已经为字符串提供了它们的行为方式与它们相同的常量类型、那么您将会有一组不同的警告。 这组不同的警告将与代码的实际行为更接近。

    我已经详细介绍了其他错误的情况

    • 用户在任何情况下都不应直接修改指针。 这样、当它可能受到 IP 堆栈的保护时、它就可以进行直接操作。 通过函数(例如 int setipaddr (const char *addr);)设置它具有多种优点
      • 您可以避免用户必须处理编译器生成的任何分配警告
      • 您可以检查地址有效性并正确返回。
    • 在任何情况下、IP 地址都不应作为字符串存储。 这样做没有特别的好处、使用上述函数、您可以将经过验证的 IP 地址转换为它表示的整数、并将其存储在栈中、而无需栈额外分析。

    后来的两个问题更有争议,但我认为有理由同时提出,因为设计错误和所涉及的设计决定确实造成了 OPS 问题。

    Robert