mensagens de aviso ao compilar o programa c usando gcc [closed]

6

Eu sou novo no linux. Eu uso o gcc (Ubuntu / Linaro 4.6.3-1ubuntu5) 4.6.3 no Ubuntu 12.04 LTS. Quando eu compilei o programa c usando o ponteiro, recebi o aviso -Wformat como mostrado abaixo. Mas se eu executar o arquivo a.out , obtenho o resultado correto. Alguém pode me dizer por que recebi a mensagem e me sugerir o que devo fazer para superar?

Meu programa de testes:

 #include<stdio.h>

void main(void)

{

int x=10,y,z;
int *p=&x ;

        printf("\n\np  = %u\n",p);
        printf("\n*p = %u\n",*p);
        printf("\n&x = %u\n",&x);
        printf("\n&y = %u\n",&y);
        printf("\n&z = %u\n",&z);
        printf("\n&p = %u\n\n",&p);
}

Saída:

qust1-Array.c:11:2: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]
qust1-Array.c:14:2: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]
qust1-Array.c:15:2: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]
qust1-Array.c:16:2: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int *’ [-Wformat]
qust1-Array.c:17:2: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int **’ [-Wformat]
    
por Thilipkumar 01.04.2013 / 14:38

1 resposta

5

Você está recebendo os avisos porque está usando o especificador de formato incorreto em printf() . p é um ponteiro inteiro. &p é o endereço de um ponteiro. &x e &y são endereços de inteiros. Estes são todos os endereços na memória, não valores de uma variável. O especificador %u é para valores de inteiros sem sinal. Então você está imprimindo maçãs onde o compilador espera laranjas. Os endereços são mais curtos do que alguns valores armazenados em variáveis. Ao usar %u , na verdade, será impresso um valor de endereço como decimal (muito incomum) e mais alguns dados localizados atrás da memória. O compilador está reclamando, porque provavelmente não é isso que você quer fazer. Para imprimir os endereços, use o especificador %p , como em:

printf("\n&x = %p\n",&x);

Além disso, suas variáveis são números inteiros assinados e, como tal, devem usar %i em vez de %u . O especificador de formato %u de printf() é apenas para inteiros positivos. Para valores positivos pequenos, %i e %u são intercambiáveis. O aviso é exibido porque o tipo de variável não corresponde ao seu especificador e isso causa problemas em alguns casos.

Isso seria mais sensato com seus tipos de variáveis:

printf("\n\np  = %p\n",  p); // p is a pointer so %p would print the address

printf("\n*p = %i\n",   *p); // the data saved at that address is an integer 
                             // so %i is appropriate if you dereference the 
                             // pointer with the star "*p"

printf("\n&x = %p\n",   &x); // &x gives the address of the integer variable x 
                             // so %p is the specifier for that address

printf("\n&y = %p\n",   &y);
printf("\n&z = %p\n",   &z);

printf("\n&p = %p\n\n", &p); // &p gives the address, where the pointer p is 
                             // stored -> still an address -> %p is the right
                             // specifier

Um fundo de bits em inteiros e ponteiros assinados e não assinados:

C usa o mesmo bit 32 (ou outro poder de dois, dependendo da arquitetura do sistema) para armazenar inteiros não assinados e assinados. Assim, a mais alta unsigned int é 2 32 -1 ou na notação binária :

  

2 32 -1 = (11111111111111111111111111111111) 2 & lt; - (sem assinatura)

E o número um ficaria assim em binário:

  

1 = (00000000000000000000000000000001) 2 & lt; - (sem assinatura)

Agora os números inteiros com sinal regulares também precisam armazenar os números negativos, mas ainda no mesmo espaço de 32 bits. Se você armazenou o sinal, do número em, e. o primeiro bit, você perderia um pouco. Isso seria um desperdício, por exemplo o zero teria duas representações como + e - zero. Para contornar este problema, números negativos em números inteiros são armazenados de forma um pouco diferente : Para codificar um número em um número inteiro com sinal, adicione metade do intervalo possível para o seu número de 32 bits. Isso é 2 (32-1) e, em seguida, use a representação binária regular desse novo número. Então, um é codificado como 2 (32-1) + 1 seria para um inteiro sem sinal. Nós temos:

  

2 (32-1) = (11111111111111111111111111111111) 2 & lt; -sign

     

...

     

1 = (10000000000000000000000000000001) 2 & lt; - assinado

     

0 = (10000000000000000000000000000000) 2 & lt; - assinado

     

-1 = (01111111111111111111111111111111) 2 & lt; - assinado

     

...

     

-2 (32-1) = (00000000000000000000000000000000) 2 & lt; -sign

Agora você codificou o mesmo número de inteiros, mas o máximo para números inteiros assinados é conseqüentemente apenas 2 (32-1) ao invés de dobrar isso, 2 32 -1, para inteiros sem sinal. Isso é chamado de representação excesso-K ou offset-binary para números negativos. A maioria dos sistemas usa o Complemento de dois , onde o primeiro bit mais significativo é invertido.

Para ver isso, defina x=-1; e, em seguida, printf("%u",x) . Você receberá a seguinte saída:

  

2147483648

Qual é 2 32-1 ou (01111111111111111111111111111111) 2 em notação binária. Para o complemento dos dois, esse número seria:

  

4294967295

Ou 2 32 -1. Isso é igual a (11111111111111111111111111111111) 2 em binário, então ele tem o primeiro bit invertido comparado ao valor de K-excesso acima de 2147483648.

Portanto, é como os dados são armazenados. Os ponteiros entram em cena quando você pensa no onde . Os bits físicos na memória devem ter endereços. Como há muitos deles, você os aborda em partes de mais de um bit. Se você criar um ponteiro, a memória física no endereço do ponteiro contém outro endereço na memória. Então, uma casa é um objeto físico, muito parecido com um pouco na memória do seu PC. Um pedaço de papel seria um ponteiro. É menor que a casa, mas pode conter o endereço de uma casa ou de outras casas. Nessa analogia, acima você teria tentado demolir o pedaço de papel em vez da casa real e era na verdade uma montanha ...

    
por con-f-use 01.04.2013 / 16:09