简体   繁体   中英

utility of #define in c++

I just found out this code from a tutorial for matrix addition in c++ by reading the values from a file-

I wanted to ask what does #define does here? What is so special in it? And how is it different from separately declaring M and N as int or char in main?

code

#include <iostream>
#include <fstream>
using namespace std;

#define M 4
#define N 5

void matrixSum (int P[M][N], int Q[M][N], int R[M][N]);
void matrixSum (int P[M][N], int Q[M][N], int R[M][N]) {
 for (int i=0; i<M; i++)    // compute C[][]
  for (int j=0; j<N; j++) 
    R[i][j] = P[i][j] + Q[i][j];
}

int main () {

 ifstream f;
 int A[M][N];
 int B[M][N];
 int C[M][N];

    f.open("values");   // open file

    for (int i=0; i<M; i++)     // read A[][]
      for (int j=0; j<N; j++) 
        f >> A[i][j];   

    for (int i=0; i<M; i++)     // read B[][]
      for (int j=0; j<N; j++) 
        f >> B[i][j];

    matrixSum (A,B,C);      // call to function

    for (int i=0; i<M; i++) {   // print C[][]
      for (int j=0; j<N; j++) 
        cout << C[i][j] << " ";
      cout << endl;
    }
    f.close();
}

The thought of const int M = 4; and const int N = 5; made the author shake in his boots because of the whopping 8 bytes of memory, so he used #define instead.

#define and other commands beginning with # are commands run by the C preprocessor before compilation begins.

Specifically, #define tells the preprocessor that everywhere the token M occurs, the text "4" should be used in its place. You are correct in that using a normal variable definition is the preferred way of accomplishing the same functionality. The reason being the variable definition is processed by the compiler with the rest of the code and #defines involve a step before compilation. More complex #defines can lead to very difficult and confusing compiler errors. If something is wrong in the #define, the line that uses the #define lists the error (since the code was copy pasted there before compilation) not the line with the #define. Nevertheless, you'll see a lot of old C style code that defines constants with #defines.

As a side note, a more general solution would be this, using function template:

template<size_t M, size_t N>
void matrixSum (int (&P)[M][N], int (&Q)[M][N], int (&R)[M][N]);

template<size_t M, size_t N>
void matrixSum (int (&P)[M][N], int (&Q)[M][N], int (&R)[M][N])
{
  for (int i=0; i<M; i++)   
    for (int j=0; j<N; j++) 
       R[i][j] = P[i][j] + Q[i][j];
}
int main () 
{

 const int M = 4; //now in main!
 const int N = 5;

 ifstream f;
 int A[M][N];
 int B[M][N];
 int C[M][N];

 //same as before
}

I think this is better than using #define , because using const or enum helps in debugging. A more detailed explanation is here:

C++ - enum vs. const vs. #define

It is a preprocessor directive of the form

#define identifier token-sequence

The preprocessor runs before the compiler transforms your code for use in the compiler. The order is as follows:

  • Trigraph replacement
  • Line splicing
  • Macro definition and expansion

So with the #define you can have character manipulation (macro substitution).

Whenever M is seen 4 will be substituted.

The compiler will then see

 void matrixSum (int P[4][5], int Q[4][5], int R[4][5]);  // ..etc

The other way would be to use the const qualifier on a global variable.

In C, it would be

// Some fileA.c  
const int M; // initialize

// Some fileB.c
const int M = 4; // defined

So I would say try to avoid when possible because macros are a form of text substitution, they do not obey scope and type rules.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM