65 votes

Les pointeurs sont-ils considérés comme une méthode d'appel par référence en C ?

Dans le cours de programmation C de mon université, la professeure et le livre qu'elle a écrit par la suite utilisent le terme appeler ou passer par référence lorsqu'il s'agit de se référer à pointeurs en C.

Un exemple de ce que mon professeur considère comme une "fonction d'appel par référence" :

int sum(int *a, int *b);

Un exemple de ce que mon professeur considère comme une "fonction d'appel par valeur" :

int sum(int a, int b);

J'ai lire Le langage C ne prend pas en charge l'appel par référence. D'après ce que j'ai compris, les pointeurs sont transmis par la valeur .

Fondamentalement, est-ce que incorrect de dire que les pointeurs sont la façon de passer par référence en C ? Serait-ce plus correct pour dire qu'il n'est pas possible de passer par référence en C mais que l'on peut utiliser des pointeurs comme solution de rechange ?


Mise à jour 11/11/15

Je pense que ma question a donné lieu à un débat terminologique et je vois en fait deux distinctions spécifiques.

  • pass-by-reference (terme principalement utilisé aujourd'hui) : Le spécifique terme utilisé dans des langages comme le C++
  • pass-by-reference (terme utilisé par mon professeur comme paradigme pour expliquer les pointeurs) : Le général terme utilisé avant le développement de langages comme le C++ et donc avant la réécriture du terme

Après avoir lu la réponse actualisée de @Haris, on comprend mieux pourquoi ce n'est pas si noir ou si blanc.

56voto

Haris Points 8474

vous ne pouvez pas passer par référence en C mais vous pouvez utiliser des pointeurs comme alternative

Oui, c'est exact.


Pour aller un peu plus loin. Tout ce que vous passez comme argument aux fonctions c, n'est transmis que par des valeurs. Qu'il s'agisse de la valeur d'une variable ou de l'adresse de la variable.

Ce qui fait la différence, c'est ce que vous envoyez.

Lorsque nous passons par la valeur, nous passons la valeur de la variable à une fonction. Lorsque nous passons par référence, nous passons un alias de la variable à une fonction. Le langage C peut transmettre un pointeur à une fonction, mais il s'agit toujours d'une transmission par valeur. Il s'agit de copier la valeur du pointeur, l'adresse, dans la fonction.


  • Si vous envoyez la valeur d'une variable, alors seule la valeur sera reçue par la fonction, et la modifier n'affectera pas la valeur originale.

  • Si vous envoyez l'adresse d'une variable, seule la valeur (l'adresse dans ce cas) est envoyée, mais comme vous avez l'adresse d'une variable, elle peut être utilisée pour modifier la valeur d'origine.


A titre d'exemple, nous pouvons voir un peu de code C++ pour comprendre la différence réelle entre call-by-value et call-by-reference. Tiré de este site web.

// Program to sort two numbers using call by reference. 
// Smallest number is output first.

#include <iostream>
using namespace std;

// Function prototype for call by reference
void swap(float &x, float &y);

int main()
{
   float a, b;

   cout << "Enter 2 numbers: " << endl;
   cin >> a >> b;
   if(a>b) 
     swap(a,b); // This looks just like a call-by-value, but in fact
                // it's a call by reference (because of the "&" in the
                // function prototype

   // Variable a contains value of smallest number
   cout << "Sorted numbers: ";
   cout << a << " " << b << endl;
   return 0;
}

// A function definition for call by reference
// The variables x and y will have their values changed.

void swap(float &x, float &y)
// Swaps x and y data of calling function
{
   float temp;

   temp = x;
   x = y;
   y = temp;
}

Dans cet exemple C++, variable de référence (qui n'est pas présent dans C) est utilisé. Pour citer este site web,

"Une référence est un alias, ou un nom alternatif à une variable existante..." ,

y

"La principale utilisation des références est de servir de paramètres formels de fonctions pour supporter le passage par référence..."

Cela diffère de l'utilisation de pointeurs en tant que paramètres de fonction car,

"Une variable pointeur (ou pointeur en abrégé) est fondamentalement la même que les autres variables, qui peuvent stocker un élément de données. Contrairement à une variable normale qui stocke une valeur (comme un int, un double, un char), un pointeur stocke une adresse mémoire."

Ainsi, lorsque l'on envoie une adresse et que l'on reçoit des pointeurs, on n'envoie que la valeur, mais lorsque l'on envoie/reçoit une variable de référence, on envoie un alias ou une référence.


MISE À JOUR : 11 novembre 2015

Un long débat a eu lieu au sein de l C Salle de discussion Après avoir lu les commentaires et les réponses à cette question, j'ai réalisé qu'il pouvait y avoir une autre façon de l'aborder, c'est-à-dire une autre perspective.

Voyons un peu de code C simple

int i;
int *p = &i;
*p = 123;

Dans ce scénario, on peut utiliser la terminologie suivante, La valeur de p est une référence à i . Donc, si c'est le cas, si nous envoyons le même pointeur ( int* p ) à une fonction, on peut affirmer que, puisque i est envoyée à la fonction, ce qui permet de l'appeler passage par référence .

Il s'agit donc d'une question de terminologie et de façon d'envisager le scénario.

Je ne suis pas complètement en désaccord avec cet argument. Mais pour une personne qui suit à la lettre le livre et les règles, ce serait une erreur.


NOTE : Mise à jour inspirée par este chat.

32voto

Hurkyl Points 1718

La référence est un terme surchargé ici ; en général, une référence est simplement un moyen de se référer à quelque chose. Un pointeur fait référence à l'objet pointé, et le passage (par la valeur) d'un pointeur à un objet est la manière standard de passer par référence en C.

Le C++ a introduit les types de référence comme meilleur moyen d'exprimer les références, et introduit une ambiguïté dans l'anglais technique, puisque nous pouvons maintenant utiliser le terme "pass by reference" pour faire référence à l'utilisation des types de référence pour passer un objet par référence.

Dans un contexte C++, la première utilisation est, IMO, dépréciée. Cependant, je pense que la première utilisation est courante dans d'autres contextes (par exemple en C pur) où il n'y a pas d'ambiguïté.

17voto

haccks Points 33022

Le langage C dispose-t-il d'un "passage par référence" ?

Pas vraiment.

Strictement parlant, le langage C utilise toujours la méthode "pass by value". Vous pouvez simuler vous-même le passage par référence, en définissant des fonctions qui acceptent des pointeurs et en utilisant ensuite la fonction & lors de l'appel de l'opérateur et le compilateur le simulera essentiellement pour vous lorsque vous passez un tableau à une fonction (en passant un pointeur à la place, voir la question 6.4 et al.).

Une autre façon de voir les choses est que *si un paramètre a un type, disons, `int ` alors un entier est transmis par référence et un pointeur sur un entier est transmis par valeur** .

Fondamentalement, le langage C n'a rien de véritablement équivalent au passage formel par référence ou à la c++ les paramètres de référence.

Pour démontrer que les pointeurs sont transmis par valeur, examinons un exemple de permutation de nombres à l'aide de pointeurs.

int main(void)
{
    int num1 = 5;
    int num2 = 10;

    int *pnum1 = &num1;
    int *pnum2 = &num2;
    int ptemp;

    printf("Before swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
    temp = pnum1;
    pnum1 = pnum2;
    pnum2 = ptemp;

    printf("After swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}

Au lieu d'échanger des nombres, on échange des pointeurs. Créez maintenant une fonction pour la même chose

void swap(int *pnum1, int *pnum2)
{
     int *ptemp = pnum1;
     pnum1 = pnum2;
     pnum2 = temp;
}

int main(void)
{
    int num1 = 5;
    int num2 = 10;

    int *pnum1 = &num1;
    int *pnum2 = &num2;

    printf("Before swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
    swap(pnum1, pnum2);

    printf("After swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}

Boom ! Pas d'échange !


Certains tutoriels mentionne la référence à un pointeur comme un appel par référence, ce qui est trompeur. Voir l'article cette réponse pour les différence entre le passage par référence et le passage par valeur .

16voto

R Sahu Points 24027

Extrait de la norme C99 (c'est moi qui souligne) :

6.2.5 Types

20 Il est possible de construire un nombre quelconque de types dérivés à partir de l'élément comme suit :

...

- A type de pointeur e peut être dérivé d'un type de fonction ou d'un type d'objet, appelé le type de fonction. type référencé . Un type de pointeur décrit un objet dont la valeur fournit une référence à une entité du type référencé. . Un type de pointeur dérivé du type référencé T est parfois appelé "pointeur sur". T ''. La construction d'un type de pointeur à partir d'un type référencé est appelée "dérivation de type de pointeur". Un type de pointeur est un type d'objet complet.

Sur la base de ce qui précède, ce que votre professeur a dit est logique et correct. Un pointeur est transmis par valeur aux fonctions. Si le pointeur pointe vers une entité valide, sa valeur fournit une référence à une entité .

10voto

tomd Points 91

Le "passage par référence" est un concept. Oui, vous transmettez la valeur d'un pointeur à la fonction, mais dans ce cas, la valeur de ce pointeur est utilisée pour référencer la variable.

Quelqu'un d'autre a utilisé l'analogie du tournevis pour expliquer qu'il n'est pas correct d'appeler le passage de pointeurs "passage par référence", en disant que l'on peut visser une vis avec une pièce de monnaie, mais que cela ne signifie pas que l'on appelle la pièce de monnaie un tournevis. Je dirais qu'il s'agit d'une excellente analogie, mais qu'elle aboutit à une conclusion erronée. En fait, même si vous ne prétendez pas qu'une pièce de monnaie est un tournevis, vous diriez quand même que vous avez vissé la vis avec cette pièce. IS en passant par une référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X