簡體   English   中英

如何在c中將uint8_t數組4轉換為uint32_t

[英]how to cast uint8_t array of 4 to uint32_t in c

我試圖將一個uint8_t數組轉換為uint32_t數組,但似乎沒有工作。
誰可以幫我這個事。 我需要將uint8_t值設為uint32_t。
我可以通過轉移來做到這一點,但我認為有一個簡單的方法。

uint32_t *v4full;
v4full=( uint32_t *)v4;
while (*v4full) {
    if (*v4full & 1)
        printf("1");
    else
        printf("0");

    *v4full >>= 1;
}
printf("\n");

鑒於需要獲取uint32_t的uint8_t值,以及in4_pton()的規格...

嘗試使用可能的字節順序更正:

uint32_t i32 = v4[0] | (v4[1] << 8) | (v4[2] << 16) | (v4[3] << 24);

如果v4full是一個指針,那么該行

uint32_t *v4full;
v4full=( uint32_t)&v4;

應拋出錯誤或至少是編譯器警告。 也許你的意思是做

uint32_t *v4full;
v4full=( uint32_t *) v4;

我假設v4本身就是指向uint8數組的指針。 我意識到我從不完整的信息中推斷......

編輯,因為上面似乎已經解決了一個錯字,讓我們再試一次。

以下代碼片段按預期工作 - 我認為您希望代碼能夠正常工作。 請評論一下 - 這段代碼怎么做不到你想要的?

#include <stdio.h>
#include <inttypes.h>

int main(void) {
    uint8_t v4[4] = {1,2,3,4};
    uint32_t *allOfIt;
    allOfIt = (uint32_t*)v4;
    printf("the number is %08x\n", *allOfIt);
}

輸出:

the number is 04030201

注意 - 打印數字中的字節順序相反 - 您可能得到04030201而不是01020304 ,這可能是您預期/想要的。 這是因為我的機器(x86架構)是小端的。 如果你想確保字節的順序是你想要的方式(換句話說,那個元素[0]對應於最重要的字節)你最好使用@ bvj的解決方案 - 移動四個字節中的每一個進入32位整數的正確位置。

順便提一下,如果需要,你可以看到這個早期的答案是非常有效的方法(告訴編譯器使用CPU的內置指令)。

您的示例存在問題 - 實際上是您正在嘗試做的事情(因為您不希望輪班)。

看,這是一個鮮為人知的事實,但是你不允許以這種方式切換指針類型

具體來說,這樣的代碼是非法的:

type1 *vec1=...;
type2 *vec2=(type2*)vec1;
// do stuff with *vec2

這是合法的唯一情況是如果type2char (或unsigned charconst char等),但是如果type2是任何其他類型(在你的例子中是uint32_t )它是違反標准的,如果你編譯可能會給你的代碼引入bug使用-O2-O3優化。

這稱為“嚴格別名規則”,它允許編譯器假設不同類型的指針從不指向內存中的相關點 - 因此,如果更改一個指針的內存,編譯器不必重新加載所有其他指針。

編譯器很難找到違反此規則的實例,除非你痛苦地清楚它。 例如,如果您更改代碼以執行此操作:

uint32_t v4full=*((uint32_t*)v4);

並使用-O3 -Wall編譯(我正在使用gcc)你會得到警告:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

所以你無法避免使用輪班。

注意:它將適用於較低的優化設置,如果您從未將信息指針更改為v4v4_full ,它也可以在更高的設置中工作。 它會工作,但它仍然是一個錯誤,仍然“違反規則”。

這是一個解決方案:

/* convert character array to integer */
uint32_t buffChar_To_Int(char *array, size_t n){
    int number = 0;
    int mult = 1;

    n = (int)n < 0 ? -n : n;       /* quick absolute value check  */

    /* for each character in array */
    while (n--){
        /* if not digit or '-', check if number > 0, break or continue */
        if((array[n] < '0' || array[n] > '9') && array[n] != '-'){
            if(number)
               break;
            else
               continue;
        }

        if(array[n] == '-'){      /* if '-' if number, negate, break */
            if(number){
               number = -number;
               break;
            }
        }
        else{      /* convert digit to numeric value   */
            number += (array[n] - '0') * mult;
            mult *= 10;
        }
    }
    return number;
}

使該代碼不可移植的另一個問題是許多架構要求uint32_t在四字節邊界上對齊,但允許uint8_t具有任何地址。 在不正確對齊的數組上調用此代碼會導致未定義的行為,例如使用SIGBUS使程序崩潰。 在這些機器上,將任意uint8_t[]強制轉換為uint32_t[]的唯一方法是memcpy()內容。 (如果以四字節塊的形式執行此操作,編譯器應針對您的體系結構優化到未對齊的負載或雙負載和移位更高效。)

如果您可以控制源數組的聲明,則可以#include <stdalign.h>然后聲明alignas(uint32_t) uint8_t bytes[] 經典的解決方案是將字節數組和32位值聲明為union成員和它們之間的type-pun。 使用從malloc()獲得的指針也是安全的,因為這些指針保證適當對齊。

還有一個解決方案

u32 ip;

if (!in4_pton(str, -1, (u8 *)&ip, -1, NULL))
      return -EINVAL;

... use ip as it defined above - (as variable of type u32)

這里我們使用in4_pton函數( ip )的結果,沒有任何額外的變量和鑄件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM