Accessing a C string from fixed Flash location - c

I have define a string at location 0xAABB:
const char str[] = "Hi There";
const word _Str1 #0xAABB = (word)str;
Now, I want to access this string located at 0xAABB.
What is the C syntax for this?

Just use a pointer to the memory location:
const char *str = (const char *)0xAABB;
Edit: (based on your comment) You need to first get the address from location 0xAABB and then use this value as the string's address:
const char *str = *(const char **)0xAABB;
This will dereference the pointer at 0xAABB to get the actual string address.

#define ADDRESS_OF_YOUR_STRING ((const char *)0xAABB)
const char *pointer_to_your_string = (const char *)0xAABB;
I could have used the macro in the pointer definition, but these are really intended to be separate demonstrations of how to do this. If you put the macro version in a header file and use it in your code the compiler will be able to optimize a little better. If you use a global pointer variable to access it then you may end up with the compiler needing to do an extra load of a pointer.
Using both of these is the same:
printf("%s\n", ADDRESS_OF_YOUR_STRING);
should work just fine since printf expects a pointer to a string for %s.

Related

function works ok w/o "const" flag. importance of "const"?

The function below uses const char *s1
What the function does is perhaps not important. It returns 1 if the string
contains characters other than allowed characters. It returns 0 if it
doesn't.
int TEST (const char *s1);
int TEST (const char *s1) {
char * s2= "o123";
return s1[ strspn(s1, s2) ] != '\0';
}
The function seems to work just fine if I were to remove const portion from it.
Why do I need const terminology in that function, if it seems to work fine without it? What is the importance of it? What are the implications of
using?
not using?
When you have const char *s1 you are telling the compiler that you will not modify the contents of the memory that s1 is pointing to. It's a semantic signal for the compiler so you do not make mistakes in the function (attempts to change the contents will results in errors). It might also allow the compiler to add some optimizations.
But more importantly it's a signal to other programmers reading your code, and using your function. And with "other programmers" I also include you in a few weeks, months or years time, when you might come back to the code and have forgotten the details of it.
importance of “const”?
3 reasons:
Applicability
Code correctness
Speed
Consider what the calling code is allowed to do
int TEST_with_const(const char *s1);
int TEST_without_const(char *s1);
char *cs;
const char *ccs
...
TEST_with_const(cs); // allowed
TEST_with_const(ccs); // allowed
TEST_without_const(cs); // allowed
TEST_without_const(ccs); // fails to compile.
The last one fails because TEST_without_const(char *s1); is telling the outside world, I want a pointer to memory that I might alter. ccs is not a pointer to modifiable memory.
Assuming TEST_without_const(char *s1); has the same body of int TEST (const char *s1), it did not need a pointer to modifiable memory
By using const char *s1 the function's body will complain during compilation should a modification of the memory pointed to by s1 is attempted. If the function design does not need to modify the memory pointed to by s1, this check helps insure correctness.
Depending on complier, some optimizations can occur with const char *, but not with char *.
const in this function prevents you to write something to memory where variable points to.
Here, you are only checking value if it is not equal to \0 and it is ok because you do only read operation.
int TEST (const char *s1) {
char * s2= "o123";
return s1[ strspn(s1, s2) ] != '\0';
}
If you do this, trying to write through s1 pointer:
int TEST (const char *s1) {
char * s2= "o123";
s1[0] = '4'; //Error, s1 is const pointer, can't write to memory pointed to by s1
return s1[ strspn(s1, s2) ] != '\0';
}
const pointer in your case means that this function should not write any data to input pointer, only read operation can be performed. You can in fact change where s1 points, only write to memory through s1 is not allowed. This is to prevent any mistakes to now write unexpectedly because it may in some cases lead to undefined behaviour.
The usage of const prevents you or somebody else working with your code from doing something accidentally wrong. Moreover it is for documentation purposes as the reader of the code knows that these functions are not changing the characters (read-only) the pointer points to.
Further the compiler may optimize your code if you use const correctness because it knows that these values are not changing inside the functions being read-only. But the first reason of documenting and making your function safer is more important.
There are three forms you always come accross with: char* s1, const char* s1 and const char* const s1. The forth but rarely needed form is: char* const. The meanings are as follows:
1.
char* s1:
In this case s1 is just a pointer to memory of one or more characters.
The following can be/can not be done inside of the function:
/* Function might changes content of s1 */
int TEST (char* s1)
{
s1[0] = 'A'; /* works */
*s1 = 'A'; /* same as above works */
++s1; /* this works because the copy of the pointer is non constant */
...
}
The following calls can be/can not be made:
char* str;
const char* const_str;
...
TEST(str); /* works as str as no restrictions */
TEST(const_str); /* fails because function might change const const_str */
2.
const char* s1:
The term: const char* s1 means s1 is a pointer to memory of one or more characters that can't be changed with this pointer. The following can be/can not be done inside of the function:
/* Function is read-only and doesn't changes content of s1 */
int CONST_TEST (const char* s1)
{
s1[0] = 'A'; /* compiler fail */
*s1 = 'A'; /* same as above compiler fail */
++s1; /* this works because the copy of the pointer is non constant */
...
}
The following calls can be/can not be made:
char* str;
const char* const_str;
...
CONST_TEST(str); /* works as str as no restrictions */
CONST_TEST(const_str); /* works because function is read-only and const_str is it also */
The compiler will fail compiling and tell you that you try to write to a memory location that is marked as constant.
3.
const char* const s1:
This means: s1 is a constant pointer to memory of one or more characters that can't be changed with this pointer. This is an extension to the first approach, the pointer s1 itself is passed by value and this copy can't be changes inside the function. So that you can not do something like ++s1 inside the function, therefore the pointer will allways point to the same memory location.
4.
char* const s1:
This is like case 3 but without s1 pointing to memory marked as constant. Therefore the content s1 is pointing to can be changed like case 1 but with a pointer being constant.

Strcpy from char* to char[] creating the wrong form

typedef struct Symbol{
char varName[16];
} Symbol;
...............
Symbol *newSymbol = malloc(sizeof(Symbol));
const char space[2] = " ";
char *String = "Name Test";
//break off the first word from String and put it into name
char *name;
name = strtok(String,space);
//convert the char * to char[16]
char nameArray[16];
strcpy(nameArray,name);
//set newSymbol->varName to the newly created char[16]
newSymbol->varName = nameArray
I have a char * called String. In my actual program, it is read from a file using fgets, I am just calling it "Name Test" for the purposes of this example. I want to take the first word of the string and assign it as the varName in a Symbol. So what should happen is newSymbol->varName is set to "Name". Because strtok returns a char * but I need a char[16] for the struct, I must convert the char * to a char[16].
However, I get this error:
"Error: incompatible types when assigning to type 'char[16]' from type 'char*'
newSymbol -> varName = nameArray;
So, it seems like strcpy it not actually converting the char * to a char[16]. Even after declaring a char[16] and telling strcpy to put the contents of the char * into it, I still have a char * instead of a char[16]. I need to make it work without changing the struct, so that is not an option here.
How can I convert a char * into a char[16]?
You cannot assign the contents of an array using the regular assignment operator in C.
You can use strcpy for strings and memcpy/memset for other data types. (You could use memcpy/memset for strings too but strcpy is simpler)
Instead of
newSymbol -> varName = nameArray;
use
strcpy(newSymbol -> varName, nameArray);
So, it seems like strcpy it not actually converting the char* to a char[16].
No, the problem is that C does not provide for assigning to (whole) arrays. newSymbol->varName is an array of 16 char. You can assign to elements of that array, and you can copy into it with strcpy() or a similar function, but you cannot assign to the whole array.
In your particular code, I'd dispense with variable nameArray, changing this ...
strcpy(nameArray,name);
... to this:
strcpy(newSymbol->varName, name);
(Or perhaps to a similar usage of strncpy(), to protect from overrunning the array bounds.)

What is the point of initializing a string pointer in C

Here is my question. in C, i saw code like this:
char *s = "this is a string";
but then, s is not actually pointing to an actual memory right?
and if you try to use s to modify the string, the result is undefined.
my question is, what is the point of assigning a string to the pointer
then?
thanks.
char *s = "this is a string";
This is a string literal. So the string is stored in read-only location and that memory address is returned to s . So when you try to write to the read-only location you see undefined behavior and might see a crash.
Q1:s is not actually pointing to an actual memory right?
You are wrong s is holding the memory address where this string is stored.
Q2:what is the point of assigning a string to the pointer then?
http://en.wikipedia.org/wiki/String_literal
When you do a char *s = "this is a string";, the memory is automatically allocated and populated with this string and a pointer to that memory is returned back to the caller (you). So, you do not need to explicitly put the string to some memory.
s is not actually pointing to an actual memory right?
Wrong, it does point to an actual memory whose allocation implementation is hidden from you. And this memory lies in the Read-Only sector of memory, so that it can't be changed/modified. Hence the keyword const as these literals are called constant literals.
if you try to use s to modify the string, the result is undefined.
Because, you are trying to modify memory which is marked as Read-Only.
what is the point of assigning a string to the pointer then?
Another way to achieve the same is,
char temp[260] = {0} ;
char *s ;
strcpy (temp, "this is a string");
s = temp ;
Here the memory temp is managed by you.
char *s = "this is a string" ;
Here the memory is managed by the OS.
By using const char * instead of a char [] the string will be stored in read only memory space. This allows the compiler to eliminate string duplication.
Try running this program:
#include <stdio.h>
int main()
{
const char *s1 = "This is a string";
const char *s2 = "This is a string";
if (s1 == s2) {
puts("s1 == s2");
} else {
puts("s1 != s2");
}
}
For the me it outputs s1 == s2 which means that the string pointers point to the same memory location.
Now try replacing const char * with char []:
int main()
{
const char s1[] = "This is a string";
const char s2[] = "This is a string";
if (s1 == s2) {
puts("s1 == s2");
} else {
puts("s1 != s2");
}
}
This outputs s1 != s2 which means that the compiler had to duplicate the string memory.
By using char * instead of char [] the compiler can do these optimizations that will decrease the size of you executable file.
Also note that you should not use char *s = "string". You should use const char *s = "string" instead. char *s is deprecated and unsafe. By using const char * you avoid the mistake of passing the string to a function that tries to modify the string.
s is not actually pointing to an actual memory right?
Technically, it is pointing to read-only memory. But the compiler is allowed to do whatever it wants as long as if follows the as-if rule. For example, if you never use s, it can be removed from your code completely.
Since it is read-only, any attempt to modify it is undefined behaviour. You can and should use const to indicate that the target of a pointer is immutable:
const char* s = "Hello const";
my question is, what is the point of assigning a string to the pointer then?
Just like storing a constant to any other type. You don't always need to modify strings. But you may want to pass a pointer to a string around to functions that don't care whether they point to a literal or to an array you own:
void foo(const char* str) {
// I won't modify the target of str. I don't care who owns it.
printf("foo: %s", str);
}
void bar(const char* str) {}
char* a = "Hello, this is a literal";
char b[] = "Hello, this is a char array and I own it";
foo(a);
bar(a);
foo(b);
Look at this code:
char *s = "this is a string";
printf("%s",s);
as you can see,I used "assigning a string to the pointer".Is that clear?
And know that s is pointing to an actual memory,but it is read-only.
If you are assigning like this,
char *s = "this is a string";
It will stored in the read only memory. So this is the reason for the undefined behavior. In this s will pointing to the some memory in the read-only area.
If you print the address like this you can get the some memory address.
printf("%p",s);
So in this case, if you allocate a memory and the copy the value to that pointer, you can access that pointer like array.
Everybody else has told you about the read-only memory and potential for undefined behavior if you attempt to modify the string, so I'll skip that part and answer the question, "what is the point of assigning a string to a pointer then?".
There are two reasons why
1) Just for brevity. After assigning the string to the pointer you can refer to the string as s instead of repeatedly typing "this is a string". This assumes of course that you intend to use the string in multiple function calls.
2) Because you may want to change the string that the pointer references. For example, in the following code, s is initialized assuming that the code will succeed, and is subsequently changed if there's a failure. At the end, the string that s points to is printed.
const char *s = "Yay, it worked!!!";
if ( openTheFile() == FAILED )
s = "Dang, couldn't open the file";
else if ( readTheFile() == FAILED )
s = "Oops, there's nothing in the file";
printf( "%s\n", s );
Note that const char * means that the string that s points to cannot be changed. It doesn't mean that s itself can't be changed.
In your case the pointer s is just pointing to the location that carries the first literal of the string. So if we want to change the string, it creates confusion as pointer s is pointing to the previous location. And if you want to change string using pointer, you should take care of the previous string's ending (i.e NULL).

Why is the param of strlen a "const"?

I'm learning the C language.
My question is:
Why is the param of strlen a "const" ?
size_t strlen(const char * string);
I'm thinking it's because string is an address so it doesn't change after initialization. If this is right, does that mean every time you build a function using a pointer as a param, it should be set to a constant ?
Like if I decide to build a function that sets an int variable to its double, should it be defined as:
void timesTwo(const int *num)
{
*num *= 2;
}
or
void timesTwo(int *num)
{
*num *= 2;
}
Or does it make no difference at all ?
C string is a pointer to a zero-terminated sequence of characters. const in front of char * indicates to the compiler and to the programmer calling the function that strlen is not going to modify the data pointed to by the string pointer.
This point is easier to understand when you look at strcpy:
char * strcpy ( char * destination, const char * source );
its second argument is const, but its first argument is not. This tells the programmer that the data pointed to by the first pointer may be modified by the function, while the data pointed to by the second pointer will remain constant upon return from strcpy.
The parameter to strlen function is a pointer to a const because the function is not expected to change what the pointer points to - it is only expected to do something with the string without altering it.
In your function 'timesTwo', if you intend to change the value that 'num' points to, you should not pass it in as a pointer-to-const. So, use the second example.
Basically, the function is promising that it will not modify the contents of of the input string through that pointer; it says that the expression *string may not be written to.
Here are the various permutations of the const qualifier:
const char *s; // s may be modified, *s may not be modified
char const *s; // same as above
char * const s; // s may not be modified, *s may be modified
const char * const s; // neither s nor *s may be modified
char const * const s; // same as above

How do I properly turn a const char* returned from a function into a const char** in C?

In short, I would like to do this:
const char **stringPtr = &getString();
However, I understand that you can't & on rvalues. So I'm stuck with this:
const char *string = getString();
const char **stringPtr = &string;
I can live with two lines. Am I introducing problems with this hack? I should have no fear of passing stringPtr out of the function it is declared in, right?
Edit: My apologies for not originally including the full context.
I have taken on the summer project of building a video game from the ground up in C using OpenGL for graphics. I'm reading configuration data from a text file using libconfig.
One of the convenience functions for finding a specific string from your configuration file looks like this:
int config_setting_lookup_string(const config_setting_t *setting,
const char *name, const char **value)
{
config_setting_t *member = config_setting_get_member(setting, name);
if(! member)
return(CONFIG_FALSE);
if(config_setting_type(member) != CONFIG_TYPE_STRING)
return(CONFIG_FALSE);
*value = config_setting_get_string(member);
return(CONFIG_TRUE);
}
The way that value is assigned means that if you give the function an uninitialized value, it attempts to derefence undefined garbage, which pretty much always causes me a segfault. My current workaround for this issue is to initialize value to another pointer first, like so:
const char *dummyPtr;
const char **fileName = &dummyPtr;
config_setting_lookup_string(foo, "bar", fileName);
So I am trying to figure out the best way to rewrite the last part of the function so that I won't have to perform this two-step initialization. I was thinking that the changed function would look like this:
int config_setting_lookup_string(const config_setting_t *setting,
const char *name, const char **value)
{
config_setting_t *member = config_setting_get_member(setting, name);
if(! member)
return(CONFIG_FALSE);
if(config_setting_type(member) != CONFIG_TYPE_STRING)
return(CONFIG_FALSE);
const char *string = config_setting_get_string(member);
value = &string;
return(CONFIG_TRUE);
}
If you're calling a function that needs a const char**, you could do it like this:
const char *s = getString();
myFunction(&s);
Since s is allocated on the stack in the above example, if you want to return a const char** from your function, you will need to put it on the heap instead:
const char **sp = malloc(sizeof(const char *));
*sp = getString();
return sp;
HTH
string in your case is a local, so taking the address of it is a bad idea since the memory for the local can (and likely will be) re-used for other purposes when you leave the method. In general, it is not a good idea to use the address of a local variable outside of its scope.
What are you trying to achieve?
No, you can't change config_setting_lookup_string() in the way you've described. You're returning a pointer to the string variable, but as soon as that function ends that variable goes out of scope and is destroyed.
You can, however, fix your initial problem quite easily. Leave the definition of config_setting_lookup_string() as it is, and call it like so:
const char *fileName = NULL;
config_setting_lookup_string(foo, "bar", &fileName);
From the added information, it seems what you are trying to do is call a function which wants to return a string through one of the function arguments. The best way to do this in my opinion would be something like:
const char* fileName;
config_setting_lookup_string(..., &fileName);
(...)
return fileName;
This will allocate room for a const char* on the stack. The function call will fill the pointer with the address of the string it wants to return. This pointer value can then be passed out of the function if needed (unlike the pointer to the pointer, which would point to the stack, and be invalid when the function returns).
Note that initializing fileName with "getString()" would presumably leak memory, since the pointer to the returned string would be overwritten, and the string never deallocated.
You need the two lines. However, string is a local variable on the stack, once it goes out of scope, you may not have a pointer to the data returned by getString().
I like nornagon and caf's solution,
const char *fileName;
config_setting_lookup_string(foo, "bar", &fileName);
but if you can change config_setting_lookup_string you could also do it this way:
int config_setting_lookup_string(..., const char *&value)
{
...
const char *string = config_setting_get_string(member);
value = string;
...
}
const char *fileName;
config_setting_lookup_string(foo, "bar", fileName);
If you return stringPtr, you will be returning a pointer to a local variable (string). So no, you can't do that.
Why are you trying to do this? That might allow us to make better suggestions.
Update:
Okay, now I see what you're trying to do. You're doing it wrong:
value = &string;
If value is meant as an output parameter, the above line cannot work because you're assigning to a local variable.
Don't let the extra level of indirection confuse you. If you were writing a function that had an output parameter of type T, you'd write it as:
void foo(T* value)
{
*value = GetT();
}
Now replace T with const char*:
...
*value = string;
...
And now you're not involving any temporary, local variables. Of course, that's how the code was originally written (and that part of it was correct), so that doesn't really help you. To address your intent, you should:
Make config_setting_lookup_string do assert(value != NULL).
Audit the callers of the function and fix them to stop passing garbage. They should be doing:
const char* foo;
config_setting_lookup_string(..., &foo);
and NOT:
const char** foo;
config_setting_lookup_string(..., foo);

Resources