Pergunta

No programa em C abaixo, eu não entendo por buf[0] = 'A' depois que eu chamo de foo.Não é foo fazendo a passagem por valor?

#include <stdio.h>
#include <stdlib.h>

    void foo(char buf[])
    {
      buf[0] = 'A';
    }

    int main(int argc, char *argv[])
    {
      char buf[10];

      buf[0] = 'B';
      printf("before foo | buf[0] = %c\n", buf[0]);
      foo(buf);
      printf("after foo | buf[0] = %c\n", buf[0]);

      system("PAUSE"); 
      return 0;
      }

saída:

before foo | buf[0] = 'B' 
after foo | buf[0] = 'A'
Foi útil?

Solução

void foo(char buf[])

é o mesmo que

void foo(char* buf)

Quando você chamá-lo, foo(buf), você passar um ponteiro de valor e, portanto, uma cópia do ponteiro é feita.

A cópia do ponteiro aponta para o mesmo objeto que o ponteiro original (ou, neste caso, a inicial do elemento da matriz).

C não tem passagem por referência semântica, no sentido de que C++ tem passagem por referência semântica.Tudo em C é passado por valor.Os ponteiros são utilizados para conseguir passar por referência semântica.

Outras dicas

Uma matriz é apenas uma maneira chique de usar um ponteiro. Quando você passa buf para a função, você está passando um ponteiro Por valor, mas quando você desrefere -se ao ponteiro, você ainda está referenciando a string para a qual aponta.

Array como parâmetro de função é equivalente a um ponteiro, então a declaração

void foo( char buf[] );

é o mesmo que

void foo( char* buf );

O argumento da matriz é então deteriorado para o ponteiro para seu primeiro elemento.

As matrizes são tratadas de maneira diferente de outros tipos; Você não pode passar uma matriz "por valor" em C.

Padrão C99 online (rascunho N1256), Seção 6.3.2.1, "Lvalues, matrizes e designadores de funções", parágrafo 3:

Exceto quando é o operando do operador de tamanho de ou do Operador Unário, ou é um literal de cordas usado para inicializar uma matriz, uma expressão que possui tipo '' Matriz do tipo '' é convertida em uma expressão com tipo '' Ponteiro para Digite '' que aponta para o elemento inicial do objeto da matriz e não é um LValue. Se o objeto da matriz tiver aula de armazenamento de registro, o comportamento será indefinido.

Na chamada

foo(buf);

a expressão da matriz buf não é o operando de sizeof ou &, nem é um literal de corda sendo usado para inicializar uma matriz, por isso é implicitamente convertido ("decans") da matriz de 10 elementos do tipo "de 10 elementos de char" para "ponteiro para char" e o Morada do primeiro elemento é passado para Foo. Portanto, qualquer coisa que você faça para buf dentro foo() será refletido no buf Array in main(). Por causa de como a assinatura da matriz é definida, você pode usar um operador subscrito em um tipo de ponteiro para que parece Como se você estivesse trabalhando com um tipo de matriz, mas você não está.

No contexto de uma declaração de parâmetro de função, T a[] e T a[N] são sinônimos de T *a, Mas isso é Caso onde isso é verdade.

*char buf [] realmente significa char ** Então você está passando por ponteiro/referência. Isso dá a você que BUF é um ponteiro, ambos no a Principal() e foo() função.

Porque você está passando um ponteiro para buf (por valor). Então o conteúdo é apontado por buf Mudou.

Com ponteiros, é diferente; Você está passando por valor, mas o que está passando é o valor do ponteiro, que não é o mesmo que o valor da matriz.

Portanto, o valor do ponteiro não muda, mas você está modificando o que está apontando.

matrizes e ponteiros são (quase) a mesma coisa.

int* foo = malloc(...)

foo[2] é o mesmo que *(foo+2*sizeof(int))

episódio:você escreveu

int main(int argc, char *argv[])

também é legal (irá compilar e funcionar da mesma) para escrever

int main(int argc, char **argv)

e também

int main(int argc, char argv[][])

eles são efetivamente o mesmo.sua mais complicado que isso, porque uma matriz sabe quantos elementos tem, e um ponteiro não.mas eles são utilizados os mesmos.

Para passar por valor por valor, a função precisaria saber o tamanho do argumento. Nesse caso, você está apenas passando um ponteiro.

Você está passando por referência aqui. Neste exemplo, você pode resolver o problema passando um único char no índice da matriz desejada.

Se você deseja preservar o conteúdo da matriz original, pode copiar a string para armazenamento temporário na função.

EDIT: O que aconteceria se você embrulsasse sua matriz de char em uma estrutura e passasse na estrutura? Acredito que isso também funcione, embora eu não saiba que tipo de despesas gerais podem criar no nível do compilador.

Por favor, observe uma coisa,

declaração

void foo(char buf[])

Diz, isso estará usando [] notação. Não qual elemento da matriz você usará.

Se você deseja apontar isso, deseja obter algum valor específico, deve declarar esta função como

void foo(char buf[X]); //where X would be a constant.

Claro que não é possível, porque seria inútil (função para operar no n-ésceiro de matriz?). Você não precisa escrever informações qual elemento da matriz você deseja obter. Tudo o que você precisa é uma declaração simples:

voi foo(char value);

assim...

void foo(char buf[])

é uma declaração que diz qual notação você deseja usar ([] - parte) e também contém ponteiro para alguns dados.

Além disso ... o que você esperaria ... você enviou para funcionar um nome de matriz

foo(buf);

que é equivalente a & buf [0]. Então ... este é um ponteiro.

Matrizes em C não são passadas por valor. Eles nem são parâmetros de função legítimos. Em vez disso, o compilador vê que você está tentando passar uma matriz e rebaixá -la para o ponteiro. Isso faz isso silenciosamente porque é mau. Também gosta de chutar filhotes.

Usar matrizes nos parâmetros de função é uma boa maneira de sinalizar para seus usuários de API que essa coisa deve ser um bloco de memória segmentado em pedaços de tamanho N-byte, mas não espere que os compiladores se importem se você soletrar char *foo char foo[] ou char foo[12] nos parâmetros da função. Eles não vão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top