Can I protect the data at the end of a pointer?

riceman0
riceman0 used Ask the Experts™
on
Hi, in C is there a way I can write a function that returns a pointer to data, in a way that ensures that the calling function can't modify the data that the pointer points to?

For example, I have a module A that acquires data, and another module B that needs to use that data.  I'd like to write a function in A like this

int *get_acquired_data(){...}

that returns a pointer to an array of acquired data, and a function in module B calls this function, receives the array, and can use the data.

However, I don't want module B to be able to modify the data; only A should be modifying the data, for module B it is read-only.  Is there a way to provide a pointer that somehow disallows that?  I don't think a const pointer will do it, right?  This probably just keeps the address constant.  Any other way to do this?

Thanks very much in advance.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Yeah you are right. You can't go for constant pointer. Why don't you try for static variables.
I think it is the best way.
Commented:
"Theoretically" you can.
For example, you can use "int* const" or "const int* const" - I attached a short example, where the compiler does not allow to change the data.
Maybe, this is already an answer for your question.

Practially, ... it can be a file opened in read-only mode? or a plaform dependent solution.
#include <stdlib.h>
 
int main()
{
	int *p1;
	const int* p2;
	int* const p3;
	const int* const p4;
	int value;
 
	value = 10;
	printf("value = %d\n", value);
 
	p1 = &value;
	*p1 = 11;
	printf("value = %d\n", value);
 
	p2 = &value;
	//error C2166: l-value specifies const object
	//*p2 = 12;
 
	//but this code is compiled well
	p2 = &value;
	p1 = p2;
	*p1 = 15;
	printf("value = %d\n", value);
 
	//two lines below are wrong:
	////error C2166: l-value specifies const object
	//p4 = &value;
	//*p4 = 12;
}

Open in new window

Author

Commented:

You mean returning the value rather than a pointer to the value?

I agree that is better in most cases.  In this case it is a large array and there is a concern about loading the stack too much if we "return" too many value copies of this data.  So, assuming we want to return a pointer to the data, is there any syntax that prevents modification of the pointed-to data by the calling function?  pointer-const, const-pointer, anything?

Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
reading your answer now pgnatyuk, sounds promising....

Author

Commented:

Ah, pgnatyuk I think I see what you're doing: *nothing* can change the value, because it is a const value, is that correct?  

What I'm looking for is a way my module B can continuously update the data, provide a pointer to module A to the data, but not worry about whether module A is changing it because it can't.

But when I put it that way, there is nothing in regular old C to do that, is there?

Author

Commented:

Actually, the below might be the way to do it.  return_data() can modify the data, but use_data() cannot.

Does this accomplish it?  Is this the same thing you did pgnatyuk?
int x;
 
 int const* return_data()
{
 
  
  x=4;
  return &x;
 
 
}
 
 
void use_data()
{
 
   int const *y = return_data();
  *y = 5;    // this doesn't compile
 
 
}

Open in new window

Commented:
so the compiler does not allow you to change x.
but:
void use_data()
{
     int const * y = return_data();
     //*y = 5; // this doesn't compile
     int* z = y;
     *z = 5;
}

Commented:
>>but not worry about whether module A is changing it because it can't
If you are writing this module A, so everything depends on you. And the way we are talking about will help you.
But you say that the module B is changing a data and module A in the same time is reading the data - can it be a sharing violation problem?

Author

Commented:

Actually I get error
error C2440: 'initializing' : cannot convert from 'const int *' to 'int *'

on

 int* z = y;  

in your suggested code

No, not in the same time, B writes it, then A reads it, then B writes it. So no sharing violation.   But C might also read it, so we want to be sure that A hasn't changed it.

Also, different developers might be writing A and B and C code.  developer of A might not be careful, so I want to protect data as best possible.

Commented:
so, probably, you have found a solution.
If it makes sense to complicate things, you can add a logical protection - a checksum, for example. You can use a shared memory maybe or a file.
Sorry, I don't know the details and can be wrong.
Top Expert 2009

Commented:
>> For example, you can use "int* const" or "const int* const"

Note that this is not 100% correct. 'int* const' is a const pointer to int. It means that the pointer is const, but the int it's pointing to isn't (it can still be modified). If you don't want to modify the int, you need 'const int*' or 'int const *' (both mean the same thing).

Note however that C isn't as strict about this as C++, so the user of the function might very well cast the const away and end up modifying the value anyway.


>> error C2440: 'initializing' : cannot convert from 'const int *' to 'int *'

This is probably because you were using a C++ compiler instead of a C compiler.
evilrixSenior Software Engineer (Avast)

Commented:
>>  I don't think a const pointer will do it, right?  This probably just keeps the address constant.  Any other way to do this?

There are 3 semantics and 5 syntaxes that can be applied to a pointer using const, thus...

char const * p; // The char is const the pointer isn't
const char * p; // Same as above
char * const p; // The pointer is const the char isn't
char const * const p; // The char is const the pointer is const
const char * const p; // Same as above

>> Can I protect the data at the end of a pointer?
Note that at any time, rightly or wrongly, const can be cast away. So the answer to your question is no as there is no guaranteed way to prevent this, only to protect it from accidental change.

int main()
{
	int const * cp;
	int * p = (int *) cp;
}

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial