Generate build error in C for not using a function

Asked

Viewed 103 times

3

A problem has arisen in creating a mini-library to simulate Threads on a PIC.

It would need to force the programmer to implement a function. I wonder if there is any way to use the preprocessors within functions and only call it if the function is used.

It would be something like this:

void teste(){
    #define _teste
}

int main(){
    teste();

    return 0;
 } 

 #ifndef _teste
     #error "Chame a funcao teste()"
 #endif

It’s possible to do it somehow?

Edit: How to return an informative error, in C, at the time of compilation for the lack of something necessary for the operation, such as a timer startup, for example, that does not generate a build error?

  • 1

    I’m not sure I understand your problem, but it seems to be an example of XY problem. That’s not the purpose of the preprocessor. If the programmer should implement a declared function somewhere and he does not, the result is a build error, which would already signal to the programmer that there is something very wrong.

  • The idea is only to allow you to run the code down only if a function has been called ? If it is clearly an XY problem

  • Right, but I would like a more informative error to make it easier to use the library. I’ll take a look at the link. And the function does not generate a build error, it just messes up the code because it is the setup of an interruption.

  • 1

    Okay, I believe XY kkk is a problem. So I’ll try to be more specific ... How to return an informative error in C at compile time by the lack of something necessary for the operation that does not generate compile error?

  • I think my answer below should satisfy you. Tell me what you think of her.

  • Yeah. That’s what I needed to know. In fact then it means that I cannot intersperse the two languages in such a way that they are conditional on one to execute the other. I’ll try to implement your idea of the bug with the code and see if I can get something relevant.

Show 1 more comment

1 answer

1

A typical C compiler has these steps, exactly in that order:

  • Preprocessing.
  • Lexical, syntactic and semantic analysis of the code.
  • Intermediate code generation (object code, these files with extension .o).
  • Linkage.
  • Generation of executable code.

Let’s assume you start with this on main.c:

void teste();

int main() {
    teste();
}

Observe the function prototype teste() there. It declares that the function exists somewhere, and that it is the linker’s responsibility to find it. If it does not, it will throw such an error (assuming you are using GCC, but it will look something like some other compiler):

/home/blablabla/blablabla.o: In function `main':
main.c:(.text.startup+0x7): undefined reference to `teste'
collect2: error: ld returned 1 exit status

Error message says the function teste was not found. It could be declared in a different file (teste.c for example):

#include <stdio.h>
void teste() {
    printf("foo");
}

And then, by compiling the two sources together, the linker will find the function teste().

You can try to get the preprocessor to work with this when doing the main be like this:

void teste();

int main() {
    teste();
}

#ifndef _teste
#   error Voce esqueceu de implementar o teste.
#endif

If the programmer does not define _teste nowhere, this error will appear. However, this solution is incomplete as there is no guarantee that the function teste() and the symbol _teste appear together. For example, the check is circumvented if the teste.c have that:

#define _teste
// Esqueci de implementar a função aqui!

Another one that goes wrong is this:

#include <stdio.h>
void teste() {
   printf("Foo");
}
// Esqueci de dar o #define _teste

In this, the error persists even if the function has been implemented.

However, this does not work at all. The preprocessor processes the files separately, so even if the programmer puts the function teste() and the symbol _teste in another file, still the error will be triggered.

You can try to remedy with a #include in the main.c:

#include "teste.inc"
void teste();

int main() {
    teste();
}

#ifndef _teste
#   error Voce esqueceu de implementar o teste.
#endif

And then, the programmer sets the function teste() and the symbol _teste within the teste.inc. However, this is not good practice of programming because header files (files with extension .h) should not be implemented. Although in this case, you are not using the header file exactly as header, but rather abusing the header definition to import an implementation (so we used a different extension, .inc).

The problem is that the preprocessor is just a tool to copy-and-paste text and is actually a language entirely separate from C. There is a language that is pre-processorprocessor and a completely different one that is the compiler and both do not communicate except because the output of one is the input of the other. Thus, it is not possible only in the preprocessor to know if the function has been declared, because the preprocessor does not even know what a function is and it sees its code only as a bunch of text to be blindly copied to the output. On the other hand, the linker (which is also separate from the compiler and pre-processor except for the fact that it uses the compiler output as input) has nothing that allows customized error messages.

We can think of a different approach. You can already provide a skeleton for the function teste and abandon the #ifdef. For example, if everything is done in a single source code:

#include <stdio.h>

void teste();

int main() {
    teste();
}

void teste() {
#   error Voce esqueceu de implementar o teste. Substitua essa mensagem pelo codigo.
}

In multiple source code, with the exception that you are abusing the purpose of #include, you can do it on main.c:

#include "teste.inc"

void teste();

int main() {
    teste();
}

And in the teste.inc:

#include <stdio.h>

void teste() {
#   error Voce esqueceu de implementar o teste. Substitua essa mensagem pelo codigo.
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.