-2

I have a function which looks like this:

void functionname(int a, char* c){
sprintf(c, " ... some text ...");
}

The above statement uses a sprintf to write into the array of 'c'.

For my system i dont think i can use sprint since i am using a different (embedded) OS.

The print function i have uses something which looks like snprintf, and i wonder how i can make this function work with snprintf.

Do i use strlen(c)? what happens when c is empty?, do i use sizeof(c)?

snprintf(c, sizeof(c), " ... text"); 

or

snprintf(c, strlen(c), "... text"); 

the function calling 'functionname' has a an array which defines the length of c as c[64]. I am afraid calling sizeof(c) will result in the size of the pointer. Also afraid that strlen will cause to return 0 when the array does not contain a string.

So the question is how can i tell snprintf to reach this value of c[64].

How can i get the size of the array the pointer c is pointing towards, and put this answer in the snprintf function. If there is a way to go from sprintf() to snprintf() with the same variables one would provide to sprintf()? in the case that sprint() function targets a char pointer?

iBeyondPower
  • 357
  • 1
  • 5
  • 8
  • 2
    `sizeof` tells you how many bytes of storage a variable uses. Remember that a pointer is a variable that points at other objects, it doesn't "contain" the things it points at. – M.M Sep 23 '15 at 12:33
  • 1
    `char * c; sizeof( c );` will give you the size of the *pointer* in bytes. (Most likely `4` or `8`, but in any case independent of whatever `c` points *to*.) `char * c; strlen( c );` will tell you how many consecutive non-`\0` bytes are in the memory area pointed to by `c` (i.e., the string length not counting the terminating `\0`). – DevSolar Sep 23 '15 at 12:35
  • 1
    "So the question is how can I tell `snprintf` to reach this value of `c[64]`" -- that is neither what the title, nor the *whole rest* of your question is talking about. I suggest asking a different question. – DevSolar Sep 23 '15 at 12:41
  • @DevSolar: fair, but note the question-behind-the-title. It's about what value to provide for `snprintf`. (Ah, you noted that while I was typing.) – Jongware Sep 23 '15 at 12:41
  • If folk (i) read the C standard, (ii) the C++ standard, (iii) the JLS, and last, but not least (iv) a regular expression tutorial, there would be no need for this site at all. – Bathsheba Sep 23 '15 at 12:43
  • @Jongware: Then the close vote should be "unclear what you're asking". Either way, a poor question that is unlikely to be helpful to future visitors.. – DevSolar Sep 23 '15 at 12:46
  • Learning the difference between `sizeof` and `strlen` is obvious from the documentation for these two things. @Bathsheba – alk Sep 23 '15 at 12:47

5 Answers5

1

With a couple of exceptions, sizeof is compile-time evaluable and gives you the size of a type. So therefore it can't know about run-time things like the length of a "string".

strlen operates on a const char* and tracks along the memory from the starting pointer until the first \0 is reached, and then returns the number of advances it makes. That's convenient since it can be used to compute the length of a "string", assuming it's modelled as a series of non-zero bytes terminated with a zero byte.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

http://linux.die.net/man/3/snprintf states that the size parameter in snprintf contains the maximum number of chars which will be written; this is a protection against writing beyond whatever storage starts at c. (Btw, c? Why not s?).

snprintf has no means to find that maximum out. The size of available memory at the destination should be known from when you allocated it (dynamically or by array definition) .

Edit: In the general case the number of bytes available at c must be passed to functionname as a parameter (for the same reason it must be passed to snprintf). That may not be necessary if the function can share, for example through a header, a #define for the array size, or if a global variable is accessible which contains the memory size.--

That said: If you are sure that the memory at c is sufficient, or if you are into unsafe programs you can, of course, pass some big number to snprintf. That will work as long as the memory indeed is sufficient for the text written at run time. The size parameter for snprintf just communicates an upper limit to snprintf which will at run time touch no memory beyond what it needs to touch.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • how do i provide this maximum number of chars in an array from the pointer, i do not have the means to find it out either (yet, i hope). – iBeyondPower Sep 23 '15 at 12:43
  • If you have no means to find out how much space there is a c, there is no safe way to copy anything into it. If you allocated it somewhere, you know; if somebody else allocated it, they should tell. – Peter - Reinstate Monica Sep 23 '15 at 12:44
  • "*pass INT_MAX to snprintf*" so what be the use of using `snprintf()` at all then? :-S – alk Sep 23 '15 at 13:02
  • @alk: The use is that it is available (as opposed to sprintf, according to the OP). I thought that this solution (i.e. the semantics of `size`) may actually not be clear to the OP. So if he doesn't have a means to find out the available space at c but can be reasonably sure that it is sufficient, there is no need to be exact. After all, that's how people programmed the buggy first 25 years. – Peter - Reinstate Monica Sep 23 '15 at 13:06
1

In this code:

void functionname(int a, char* c){
    sprintf(c, " ... some text ...");
}

c is a mere pointer, not an array. So sizeof(c) will be sizeof(char *), that is 2, 4 or 8 depending on architecture (resp. 16, 32 or 64 bits).

strlen(c) only gives the position on first null in memory starting at c. If the array was initialized to 0 by caller, it will just be... 0!

So here neither can be used. The best way would be to ask caller to pass the actual size of the array and just be confident in callee:

void functionname(int a, char* c, size_t size){
    snprintf(c, size, " ... some text ...");
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
1

how can i get the size of the array the pointer c is pointing towards,

You cannot.

The code needs to keep track of how much valid memory a pointer points to.

A pointer does not hold information of the size of valid memory it is pointing to but just only the address of a memory area, which might even be of size 0.

alk
  • 69,737
  • 10
  • 105
  • 255
  • there is no way to go from sprintf() to snprintf() with the same variables one would provide to sprintf()? in the case that print function targets a char pointer? – iBeyondPower Sep 23 '15 at 12:47
  • 1
    @iBeyondPower: If you have no array variable to determine its size from (using the `sizeof`-operator), but only a pointer and no other reliable info on the size of valid memory the pointer points then yes, there is no way. – alk Sep 23 '15 at 12:55
0

Since c is a pointer, sizeof(c) will return the size of a pointer, which depends on the architecture of your platform, e.g. 32 bits -> 4, 16 bits -> 2.

strlen(c) will not help you either, because it calculates the length of the string by stopping at the first null character.
If your buffer is uninitialized, it is no better than undefined behaviour.

You need to know the real size of the buffer that c refers to.

The buffer can be allocated on the stack statically, like this:

char buffer[250];
char * c = buffer;

Or dynamically:

int sz = 250;
char * buffer = malloc(sz * sizeof(char));
char * c = buffer;

You need to know its real size (here 250), by passing it explicitely to the function that calls your sprintf variant:

void functionname(int a, char* c, int sz){
    snprintf(c, sz, " ... some text ...");
}

I am assuming here that a is a completely unrelated variable.

SirDarius
  • 41,440
  • 8
  • 86
  • 100