Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Wrong implementation (compiled with gcc):
#include <stdio.h>
#include <ctype.h>
char* strupr( char *str )
{
while(*str) {
*str++ = toupper(*str);
}
return str;
}
int main(void) {
char string[] = { "Test String!" };
strupr( string );
puts( string );
return 0;
}
The function changes the string in an unexpected way, where the chars translated to upper case are only starting from the second char.
Note str is used twice in the assignment.
This implementation is invalid because it contains undefined behavior.
The explanation comes from section 6.5, paragraph 2 of the standard:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
The standard gives an example of an expression that is considered undefined behavior to clarify the second sentence:
a[i++] = i;
In this expression the value of i is read not only to determine the new value to be stored, but also to determine the storage location of another value.
This is precisely what is happening in your expression:
*str++ = toupper(*str);
The only difference is that your expression uses pointers, and calls toupper in between.
This requirement may seem arbitrary, but it has a reason. C standard allows the compiler to make side effects of ++ visible before or after the call of toupper to allow compiler writers maximum flexibility. Without a restriction on str's use in expression this could lead to different behavior on different platforms, so the standard writers decided to prohibit it outright.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
int main(void)
{
char mine[5] = "hello";
char *pen = mine;
while(*pen != '\0')
{
printf("%c\n", *pen);
pen++;
}
}
int main(void)
{
char mine[5] = "hello";
char *pen = mine;
while(*pen != '\0')
{
printf("%c\n", *pen);
*pen++;
}
}
I'm trying to grasp the idea of pointers with string. I ran both of the codes and got the same result, but I got a warning on the 2nd version of the code with *pen++ but still was able to run.
What is each of them doing and how come it gave me the same output?
According to the rules on operator precedence, the line
*pen++;
is equivalent to
*(pen++);
which means the * does nothing. So it is doing exactly the same thing as the line
pen++;
in the first program.
Also, it is important to note that the line
char mine[5] = "hello";
is not doing what you expect. You are initializing a character array of length 5 with a string literal of length 6 (including the terminating null character). This means the array does not contain sufficient space for the terminating null character.
Therefore, you should change the line to the following:
char mine[6] = "hello";
Alternatively, in order to make the compiler automatically allocate a sufficient amount of memory for the initialization, you can just write the following:
char mine[] = "hello";
pen++; is a statement consisting of one expression pen++. This expression's value is pen and the side effect is that pen is incremented.
*pen++ is a statement constisting of one expression *pen++. The expression's value is *pen and the side effect is that pen is incremented.
When an expression is used as a statement, then the value of the expression is ignored, only the side effects are relevant/observable. So in your case it is irrelevant if pen or *pen is the value, the side effect of incrementing pen is identical in both cases. Thus in your program both variants have the same observable effect. Yet it does not make sense to write *pen++ if you don't want to use the value. Then you should just write pen++, or even better ++pen.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm trying to convert a char array to upper case in C. But it still prints out in lower case. The logic in conversion function looks okay to me. I don't know if the problem could be that the input I'm passing to this function is member of a structure variable.
This is the structure whose member I'm passing to conversion function:
typedef struct AESParams {
unsigned char output[192];
} AESParams;
My conversion fucntion is shown below:
void stringUpr(char *s)
{
int i=0;
while(s[i]!='\0')
{
if(s[i]>='a' && s[i]<='z'){
s[i]=s[i]-32;
}
++i;
}
}
I call conversion function as follows:
AESParams parameters;
stringUpr(parameters.output);
If I print the output after calling "stringUpr" function, the value is still in lower case. Can anyone tell me what might be causing the issue here?
TIA...
Update: Code that writes value to output.
EVP_EncryptUpdate(&ctx, parameters->output, &outLen, input, length);
// This call happens in some other file. parameters is passed to the function that calls this function and after computation parameters is passed back to the place where I'm calling stringUpr().
I'm confident that this lines works and it gives the correct results after computation. It's just that I want to take this value and convert to upper case and write to a file.
Your program assumes that it's running using an ASCII character set, which is not guaranteed. Use the standard functions defined in ctype.h
void stringUpr(char* s)
{
int i = 0;
while(s[i] != '\0')
{
s[i++] = toupper((unsigned char)s[i]);
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
Can anyone explain what will be the output of following code and why?
int main()
{
int i[] = {3, 5};
int* p = i;
int j = --*p++;
printf("%d\n%d\n", j,*p);
system("pause");
return 0;
}
I'm actually going to answer this question, even though it's true that "the OP simply needs to compile the code and run it", because it isn't obvious to a beginner that this is one of the cases where that gives the right answer. People get dinged all the time on this site for asking why superficially similar code (that does have undefined behavior) gives a surprising answer.
int j = --*p++;
means
int j = *p - 1;
*p = j;
p += 1;
That is, *p (the value that p points to) is decremented, the decremented value is written to j, and then p itself is incremented.
There is no undefined behavior here because the -- and ++ operators in the original form are acting on two different data objects. The expressions that have undefined behavior due to multiple use of the side-effect operators all involve modifying the same data object twice in the same expression ("without an intervening sequence point").
(If you're wondering why the -- applies to *p but the ++ applies only to p, the answer is "because that's what the grammar of the language says. Sorry, this is just one of those things you have to memorize.")
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
C code related to the question:
#include <stdio.h>
int main(int argc, char **argv)
{
int k = 0;
double b = k++ + ++k + k--;
printf("%d", k);
return 0;
}
The value stored in b is undefined, but what about k?
The place where I found this:
http://www.sanfoundry.com/online-c-test-precedence-order-evaluation/ Question #10
--EDIT--
What I found so far:
The value stored in b is not used anywhere, so if storing something into b would be the only UB, this program would not depend on UB.
But I also found this part in C99 6.5.2:
"Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression."
And listed under J.2. Undefined behavior:
" The behavior is undefined .... ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint is violated"
But the actual question is not answered yet.
-- EDIT #2 --
Not that I'm trying to write one, but a ''A strictly conforming program'' according to the standard :
"shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior"
So the orignal example was wrong, since it did depend on undefined behaviour, it would be undefined even if one would replace the line
double b = k++ + ++k + k--;
with the line
k++ + ++k + k--;
So right now I'm looking for a better presentation of what question is about.
As soon as we hit undefined behaviour, the compiler can do whatever it wants to - including formatting the disk if it has access rights. So nothing can be defined in this situation, including side effects.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
int main()
{
int a=1;
printf("%d %d %d",a,a++,++a);
return 0;
}
The above code is giving output 3 2 3 why????
It actually undefined in c and c++.
Undefined : modifying a scalar value twice between sequence points, which is what your code is doing. f(i++, ++i) is undefined behaviour because it modifies i twice without an intervening sequence point.
A good list of definitions
This is undefined behaviour
a++, ++a is done in same sequence point and this is undefined behaviour.
From Undefined behavior and sequence points :
In the Standard in §5/4 says
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of
an expression.
What does it mean?
Informally it means that between two sequence points a variable must not be modified more than once. In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.
The mechanics of pre- and postincrementing are described here : http://c-faq.com/expr/evalorder2.html . However, this expression is undefined as mentioned in the previous answers.