Najiva
Najiva

Reputation: 162

How to make sure pointer and its content passed to a function cannot be modified only within function block in c

I was wondering and could not find an answer to my question anywhere. Lets say I do have two functions:

void function_B(int * data){
 // I am able to modify its content
}

void function_A(int * data){
 // I do not want to be able to modify the data nor its content here only pass the pointer to function B, so it can be changed there
    function_B(data); 
 // Nor I want to be able to modify it here
}

I am familiar with the const keyword, but if I make the data and the pointer constant for function A, it cannot be changed also by the function B. How could I write such a code? Is this even possible with c?

Upvotes: 3

Views: 1108

Answers (4)

machine_1
machine_1

Reputation: 4454

According to your problem statement, function_B() has to be called within function_A(), and it shall modify the content pointed to by the pointer data. This signify that the pointer passed to to function_B() must not be declared as const.

As such, if the pointer data has to come from the caller function_A(), then it is going to be able to modify what precedes the call to the function function_B(), and you can't do anything about it.

You can however declare a const pointer within function_A() that points to the content of the non-const pointer data, and give it the suffix _A to mean that this pointer shall be used in place of the original pointer data within function_A().

void function_B(int * data) {
    // I am able to modify its content
}

void function_A(int * data) {
    const int *data_A = data;
    // data_A can't change anything...


    // I do not want to be able to modify the data nor its content here only pass the pointer to function B, so it can be changed there
    function_B(data);
    // Nor I want to be able to modify it here
}

Upvotes: 1

Ian Abbott
Ian Abbott

Reputation: 17403

One thing you could do is factor out the parts of function_A that are not allowed to modify the data, something like this:

void func_A_preB(const int *data)
{
    // Do stuff with data but don't change it.
}

void func_A_postB(const int *data)
{
    // Do stuff with data but don't change it.
}

void function_B(int *data)
{
    // Can change data.
}

void function_A(int *data)
{
    func_A_preB(data);
    function_B(data);
    func_A_postB(data);
}

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 148900

It is questionable design to forbid change in one function but allow it in a called function. But it is indeed allowed by the C standard. As others have already said, the trick is to change function_A. The simplest change would be:

void function_A(const int * data){
 // I do not want to be able to modify the data nor its content here only pass the pointer to function B, so it can be changed there
    function_B((int *) data); 
 // Nor I want to be able to modify it here
}

But it bad design because the prototype of function_A makes a promise to never change data and does change it. If you pass an array which was initially declare as const, you will even invoke undefined behaviour:

const int arr[] = {1, 2, 3};
function_A(arr);     // will compile because function_A declared a const param

In function_B you will try to change a const object which is explicitely UB.


The correct way (which may or not be acceptable for your use case) is to use an auxiliary variable:

void function_A(int * _data){
 const int *data = _data;   // always valid
 // data cannot be used to change anything, but of course _data could
 // data[0] = 1; would raise a compilation error
    function_B(_data); 
 // Nor I want to be able to modify it here
}

Upvotes: 1

Jabberwocky
Jabberwocky

Reputation: 50775

The only thing you can do is this:

void function_B(int * data) {
  *data = 0;
}

void function_A(const int * data) { // << add the const keyword here
  *data = 0;               // this won't compile (which is what you intend)
  function_B(data);        // this won't compile either, but that's what you want to do

  function_B((int*)data);  // but this will compile
}

In function_A, data is a const pointer so you cannot modify the data it points to, but you cannot pass it to a function whose parameter is a non const (like function_B in this example) either.

But you can cast the const away like in the example above.

Keep in mind that this is still a very questionable design, as casting away a const defies it's very own purpose as it results in undefined behaviour if the data passed to function_A is constant.

const int a = 2;
int b = 2;

int main()
{
  function_A(&a);  // a is constant => results in undefined behaviour
                   // when function_B tries to modify the data

  function_A(&b);  // OK
}

Upvotes: 0

Related Questions