This is a general issue I've run into, and I've yet to find a solution to it that doesn't feel very "hack-y". Suppose I have some array of elements xs = {a_1, a_2, ..., a_n}, where I know some x is in the array. I wish to loop through the array, and do something with each element, up to and including the element x. Here's a version that does almost that, except it leaves out the very last element. Note that in this example the array happens to be a sorted list of integers, but in the general case this might not necessarily be true.
int xs[] = {1,2,3,4,5};
for (int i = 0; xs[i] != 4; i++) {
foo(xs[i]);
}
The only solutions I've seen so far are:
Just add a final foo(xs[i]); statement after the for-loop. This is first of all ugly and repetitious, especially in the case where foo is not just a function call but a list of statements. Second, it requires i to be defined outside the scope of the for-loop.
Manually break the loop, with an if-statement inside an infinite loop. This again seems ugly to me, since we're not really using the for and while constructs to their full extent. The problem is almost archetypal of what you'd use a for-loop for, the only difference is that we just want it to go through the loop one more time.
Does anyone know of a good solution to this problem?
In C, the for loop is a "check before body" operation, you want the "check after body" variant, a do while loop, something like:
int xs[] = {1,2,3,4,5};
{
int i = 0;
do {
foo(xs[i]);
} while (xs[i++] != 4);
}
You'll notice I've enclosed the entire chunk in its own scope (the outermost {} braces). This is just to limit the existence of i to make it conform more with the for loop behaviour.
In terms of a complete program showing this, the following code:
#include <stdio.h>
void foo(int x) {
printf("%d\n", x);
}
int main(void) {
int xs[] = {1,2,3,4,5};
{
int i = 0;
do {
foo(xs[i]);
} while (xs[i++] != 4);
}
return 0;
}
outputs:
1
2
3
4
As an aside, like you, I'm also not that keen of the two other solutions you've seen.
For the first solution, that won't actually work in this case since the lifetime of i is limited to the for loop itself (the int in the for statement initialisation section makes this so).
That means i will not have the value you expect after the loop. Either there will be no i (a compile-time error) or there will be an i which was hidden within the for loop and therefore unlikely to have the value you expect, leading to insidious bugs.
For the second, I will sometimes break loops within the body but generally only at the start of the body so that the control logic is still visible in a single area. I tend to do that if the for condition would be otherwise very lengthy but there are other ways to do this.
Try processing the loop as long as the previous element (if available) is not 4:
int xs[] = {1,2,3,4,5};
for (int i = 0; i == 0 || xs[i - 1] != 4; i++) {
foo(xs[i]);
}
This may not be a direct answer to the original question, but I would strongly suggest against making a habit of parsing arrays like that (it's like a ticking bomb waiting to explode at a random point in time).
I know you said you already know x is a member of xs, but when it is not (and this can accidentally happen for a variety of reasons) then your loop will crash your program if you are lucky, or it will corrupt irrelevant data if you are not lucky.
In my opinion, it is neither ugly nor "hacky" to be defensive with an extra check.
If the hurdle is the seemingly unknown length of xs, it is not. Static arrays have a known length, either by declaration or by initialization (like your example). In the latter case, the length can be calc'ed on demand within the scope of the declared array, by sizeof(arr) / sizeof(*arr) - you can even make it a reusable macro.
#define ARRLEN(a) (sizeof(a)/sizeof(*(a)))
...
int xs[] = {1,2,3,4,5};
/* way later... */
size_t xslen = ARRLEN(xs);
for (size_t i=0; i < xslen; i++) {
if (xs[i] == 4) {
foo( xs[i] );
break;
};
}
This will not overrun xs, even when 4 is not present in the array.
EDIT:
"within the scope of the declared array" means that the macro (or its direct code) will not work on an array passed as a function parameter.
// This does NOT work, because sizeof(arr) returns the size of an int-pointer
size_t foo( int arr[] ) {
return( sizeof(arr)/sizeof(*arr) );
}
If you need the length of an array inside a function, you can pass it too as a parameter along with the array (which actually is just a pointer to the 1st element).
Or if performance is not an issue, you may use the sentinel approach, explained below.
[end of EDIT]
An alternative could be to manually mark the end of your array with a sentinel value (a value you intentionally consider invalid). For example, for integers it could be INT_MAX:
#include <limits.h>
...
int xs[] = {1,2,3,4,5, INT_MAX};
for (size_t i=0; xs[i] != INT_MAX; i++) {
if (xs[i] == 4) {
foo( xs[i] );
break;
};
}
Sentinels are quite common for parsing unknown-length dynamically-allocated arrays of pointers, with the sentinel being NULL.
Anyway, my main point is that preventing accidental buffer overruns probably has a higher priority compared to code prettiness :)
Related
I am new to SO - I have a question which I was asked in interview and which for life of me I am not able to wrap my head around. I can solve it with while/for loop but interviewer specifically asked not to use them I even discussed with few friends of mine but unable to solve it. If someone can provide pointers.
Question is:
for given array
s[] = {5,1,0,4,2,3}
length of array is not given.
If length of array is 5 content
is guaranteed to be between 0 to 5.
There is no repetition of
numbers.
Sample example length(s, 3)
- a[3] = 4 , a[4] = 2, a[2] = 0, a[0] = 5, a[5] =3 returns length of 4 .
For given condition write subroutine int length (s, 3) - to find the number of steps it takes to find given value -
Additional conditions
You cannot use any loop statements like for, while and so on -
You cannot use any global or static variables.
You cannot call other routines inside this routine
You cannot modify given function parameters - it stays length (s, n) only
You cannot change original array too
Alternative solution that does not modify the array at all, but hides an extra parameter inside top 16 bits of x:
int length(int *s, int x){
int start = (x >> 16) - 1;
if (start < 0)
start = x;
if (s[x] == start)
return 0;
return 1 + length(s, ((start + 1) << 16) + s[x]);
}
This will fail if there are too many elements in the array, but I suspect any other recursive solution is likely to hit a stack overflow by that point in any case.
I think I found the answer eventually no I didnt crack it but found it online :) .. Here is the solution
int length(int * s, int x){
if(s[x] < 0){
return -1;
}
else{
s[x] = -s[x];
int len = length(s, -s[x]);
s[x] = -s[x];
return len + 1;
}
}
i don't think it contradicts with any of your conditions. i just didn't use the array as a parameter (that isn't a problem actually, you can modify it yourself)
int s[] = {5,1,0,4,2,3};
bool col[100]; ///to check cycle
int rec(int n)
{
if(col[n])return 0;
col[n]=true;
int sum=0;
sum = 1+rec(s[n]);
return sum;
}
The interviewer is probing your understanding of algorithms and programming paradigms, trying to understand your training, background, and depth. The interviewer has a challenging task; identifying capable developers with minimal evidence. Thus the interviewer presents a constructed problem that (they hope) elicits the desired knowledge (does candidate X know how to solve problem Y, or understand concept Z) perhaps because the interviewer believes the desired answer indicates the candidate knows the expected body of knowledge.
Modern languages provide several repetition structures (commands, statements), some which pre-test (check condition before entering statement-block), and some which post-test (check condition after performing statement block at least once). Here are examples,
Pre-test
while(condition) statement-block
for(initializer;condition;step) statement-block
Post-test
do statement-block while(condition)
repeat statement-block until(condition)
do statement-block until(condition)
These can all be written as conditional (choice) structures with branching (goto),
Pre-test
label:
if(condition)
statement-block;
goto label;
else
nil;
endif
Post-test
label:
statement-block;
if(condition)
goto label;
endif
You can also use recursion, where you call the same function as long as condition holds (or until condition met, depending upon positive or negative logic),
Pre-test
function recurse(args)
if(condition)
statement-block
recurse(revised args);
endif
return
end #function
Post-test
function recurse(args)
statement-block
if(condition)
recurse(revised args);
endif
return;
end
You would learn about recursion in an algorithms, or perhaps a computability course. You would learn about conditional branching in a compiler, high performance computing, or systems class. Your compiler course might examine techniques for detecting 'tail-recursion', and how to rewrite the function call into a loop.
Here is the problem, restated,
given array, s[] = {5,1,0,4,2,3}
array length unknown
content between [0 .. length], not repeated, no duplicates
write subroutine which provides the number of steps to find given value
That is,
int length( array s, int member ) --> position
Examine the conditions (constraints) on the problem,
Array length unknown - Solution must work for variable range of inputs
Cannot use loop statements (for, while, etc) - This suggests either the interviewer wants conditional branch or recursion.
Cannot use global or static variables - Does this suggest interviewer wants a recursive/functional-programming solution? Conditional-branch also provides this.
Cannot call other routines inside this routine - Does interviewer mean functions other than same function, or call any function (what does interviewer mean by 'other').
Cannot modify function parameters, stays length(s,n) - Declaring local (stack) variables is allowed. This could mean pass by value, make a local copy, etc. But not destructive modifications.
Cannot change original array - Definitely no destructive modifications. Possible 'hint' (ok to make local copy?), or further indication that you should use conditional-branch?
Here are two solutions, and a test driver (note, I have named them lengthi, iterative, and lengthr, recursive).
#include <stdio.h>
/* conditional branch */
int lengthi( int s[], int member )
{
int position=0;
AGAIN:
if( s[position] == member ) return(position);
++position;
goto AGAIN;
return(-1);
}
/* recursive */
int lengthr( int s[], int member )
{
if( s[0] == member ) return(0);
return( 1+length(s+1,member) );
}
int
main(int argc,char* argv[])
{
int s1[] = {0,1,2,3,4,5,6,7,8,9};
int s2[] = {1,2,3,4,9,8,7,6,0,5};
int s3[] = {2,4,6,8,0,1,3,5,7,9};
printf("%d at %d\n",3,lengthr(s1,3));
printf("%d at %d\n",3,lengthr(s2,3));
printf("%d at %d\n",3,lengthr(s3,3));
printf("%d at %d\n",3,lengthi(s1,3));
printf("%d at %d\n",3,lengthi(s2,3));
printf("%d at %d\n",3,lengthi(s3,3));
}
Since we are supposed to find the number of steps (iterations, function calls), that is asking for the ordinal position in the list, not the C index (zero based) position.
This is an interview question, and not a programming problem (per se), so probably better suited for the Programmers.stackexchange site. I might give the interviewer an entertaining answer, or their desired answer.
This is a generic question, so there is no actual code that I am trying to troubleshoot. But what I want to know is, can I use a for loop to change the name of a variable in C? For instance, if I have part1, part2, part3, part..., as my variable names; is there a way to attach it to my loop counter so that it will increment with each passing? I toyed around with some things, nothing seemed to work.
In C, you can't 'change the name of the loop variable' but your loop variable does not have to be determined at compile time as a single variable.
For instance, there is no reason in C why you can't do this:
int i[10];
int j;
j = /* something */;
for (i[j] = 0 ; i[j] < 123 ; i[j]++)
{
...
}
or event supply a pointer
void
somefunc f(int *i)
{
for (*i = 0; *i<10; *i++)
{
...
}
}
It's not obvious why you want to do this, which means it's hard to post more useful examples, but here's an example that uses recursion to iterate a definable number of levels deep and pass the innermost function all the counter variables:
void
recurse (int levels, int level, int max, int *counters)
{
if (level < levels)
{
for (counters[level] = 0;
counters[level] < max;
counters[level]++)
{
recurse (levels, level+1, max, counters);
}
return;
}
/* compute something using counters[0] .. counters[levels-1] */
/* each of which will have a value 0 .. max */
}
Also note that in C, there is really no such thing as a loop variable. In a for statement, the form is:
for ( A ; B ; C ) BODY
Expression A gets evaluated once at the start. Expression B is evaluated prior to each execution of BODY and the loop statement will terminate (and not execute BODY) if it evaluates to 0. Expression C is evaluated after each execution of BODY. So you can if you like write:
int a;
int b = /* something */;
int c = /* something */;
for ( a=0; b<5 ; c++ ) { ... }
though it will not usually be a good idea.
The answer is, as #user2682768 correctly remarked, an array. I am not sure whether you are aware of that and consciously do not want to use an array for some reason; your little experience doesn't give me enough information. If so, please bear with me.
But you'll recognize the structural similarity between part1, part2, part3... and part[1], part[2], part[3]. The difference is that the subscript of an array is variable and can be changed programmatically, while the subscript part of a variable name cannot because it is burned in at compile time. (Using macros introduces a meta compiling stage which lets you programmatically change the source before actually compiling it, but that's a different matter.)
So let's compare code. Say you want to store the square of a value in a variable whose name has the value as a suffix. You would like to do something like
int square1, square2, square3;
int i;
for(i=1; i<=3; i++)
{
square/i/ = i*i; /* /i/ to be replaced by suffix "i".
}
With arrays, that changes to
int square[4];
int i;
for(i=1; i<=3; i++)
{
/* the (value of) i is now used as an index in the array.*/
square[i] = i*i;
}
Your idea to change the variable name programmatically implies that all variables have the same type (because they would have to work in the same piece of code, like in my example). This requirement makes them ideally suited for array elements which all have to be of the same type. If that is too restrictive, you need to do something fancier, like using unions (but how do you know what's in it at any given moment? It's almost as if you had different variables to begin with), void pointers to untyped storage or C++ with templates.
In C You cannot append to a variable name an expression that expands to a number and use it as a sort of suffix to access different variables that begin in the same way.
The closest you can get, is to "emulate" this behaviour using a switch construct, but there wouldn't be much of a point to try to do this.
What you asked for is more suited to scripting languages.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Is this type of expression in C valid (on all compilers)?
If it is, is this good C?
char cloneString (char clone[], char string[], int Length)
{
if(!Length)
Length=64
;
int i = 0
;
while((clone[i++] = string[i]) != '\0', --Length)
;
clone[i] = '\0';
printf("cloneString = %s\n", clone);
};
Would this be better, worse, indifferent?
char *cloneString (char clone[], char string[], int Length)
{
if(!Length)
Length=STRING_LENGTH
;
char *r = clone
;
while
( //(clone[i++] = string[i]) != '\0'
*clone++ = *string++
, --Length
);
*clone = '\0';
return clone = r
;
printf("cloneString = %s\n", clone);
};
Stackoverflow wants me to add more text to this question!
Okay! I'm concerned about
a.) expressions such as c==(a=b)
b.) performance between indexing vs pointer
Any comments?
Thanks so much.
Yes, it's syntactically valid on all compilers (though semantically valid on none), and no, it isn't considered good C. Most developers will agree that the comma operator is a bad thing, and most developers will generally agree that a single line of code should do only one specific thing. The while loop does a whole four and has undefined behavior:
it increments i;
it assigns string[i] to clone[i++]; (undefined behavior: you should use i only once in a statement that increments/decrements it)
it checks that string[i] isn't 0 (but discards the result of the comparison);
it decrements Length, and terminates the loop if Length == 0 after being decremented.
Not to mention that assuming that Length is 64 if it wasn't provided is a terrible idea and leaves plenty of room for more undefined behavior that can easily be exploited to crash or hack the program.
I see that you wrote it yourself and that you're concerned about performance, and this is apparently the reason you're sticking everything together. Don't. Code made short by squeezing statements together isn't faster than code longer because the statements haven't been squeezed together. It still does the same number of things. In your case, you're introducing bugs by squeezing things together.
The code has Undefined Behavior:
The expression
(clone[i++] = string[i])
both modifies and accesses the object i from two different subexpressions in an unsequenced way, which is not allowed. A compiler might use the old value of i in string[i], or might use the new value of i, or might do something entirely different and unexpected.
Simple answer no.
Why return char and the function has no return statement?
Why 64?
I assume that the two arrays are of length Length - Add documentation to say this.
Why the ; on a new line and not after the statement?
...
Ok so I decided to evolve my comments into an actual answer. Although this doesn’t address the specific piece of code in your question, it answers the underlying issue and I think you will find it illuminating as you can use this — let’s call it guide — on your general programming.
What I advocate, especially if you are just learning programming is to focus on readability instead of small gimmicks that you think or was told that improve speed / performance.
Let’s take a simple example. The idiomatic way to iterate through a vector in C (not in C++) is using indexing:
int i;
for (i = 0; i < size; ++i) {
v[i] = /* code */;
}
I was told when I started programming that v[i] is actually computed as *(v + i) so in generated assembler this is broken down (please note that this discussion is simplified):
multiply i with sizeof(int)
add that result to the address of v
access the element at this computed address
So basically you have 3 operations.
Let’s compare this with accessing via pointers:
int *p;
for (p = v; p != v + size; ++p) {
*p = /*..*/;
}
This has the advantage that *p actually expands to just one instruction:
access the element at the address p.
2 extra instructions don’t seam much but if your program spends most of it’s time in this loop (either extremely large size or multiple calls to (the functions containing this) loop) you realise that the second version makes your program almost 3 times faster. That is a lot. So if you are like me when I started, you will choose the second variant. Don’t!
So the first version has readability (you explicitly describe that you access the i-th element of vector v), the second one uses a gimmick in detriment of readability (you say that you access a memory location). Now this might not be the best example for unreadable code, but the principle is valid.
So why do I tell you to use the first version: until you have a firm grasp on concepts like cache, branching, induction variables (and a lot more) and how they apply in real world compilers and programs performance, you should stay clear of these gimmicks and rely on the compiler to do the optimizations. They are very smart and will generate the same code for both variants (with optimization enabled of course). So the second variant actually differs just by readability and is identical performance-wise with the first.
Another example:
const char * str = "Some string"
int i;
// variant 1:
for (i = 0; i < strlen(str); ++i) {
// code
}
// variant 2:
int l = strlen(str);
for (i = 0; i < l; ++i) {
// code
}
The natural way would be to write the first variant. You might think that the second improves performance because you call the function strlen on each iteration of the loop. And you know that getting the length of a string means iterating through all the string until you reach the end. So basically a call to strlen means adding an inner loop. Ouch that has to slow the program down. Not necessarily: the compiler can optimize the call out because it always produces the same result. Actually you can do harm as you introduce a new variable which will have to be assigned a different register from a very limited registry pool (a little extreme example, but nevertheless a point is to be made here).
Don’t spend your energy on things like this until much later.
Let me show you something else that will illustrate further more that any assumptions that you make about performance will be most likely be false and misleading (I am not trying to tell you that you are a bad programmer — far from it — just that as you learn, you should invest your energy in something else than performance):
Let’s multiply two matrices:
for (k = 0; k < n; ++k) {
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
r[i][j] += a[i][k] * b[k][j];
}
}
}
versus
for (k = 0; k < n; ++k) {
for (j = 0; j < n; ++j) {
for (i = 0; i < n; ++i) {
r[i][j] += a[i][k] * b[k][j];
}
}
}
The only difference between the two is the order the operations get executed. They are the exact same operations (number, kind and operands), just in a different order. The result is equivalent (addition is commutative) so on paper they should take the EXACT amount of time to execute. In practice, even with optimizations enable (some very smart compilers can however reorder the loops) the second example can be up to 2-3 times slower than the first. And even the first variant is still a long long way from being optimal (in regards to speed).
So basic point: worry about UB as the other answers show you, don’t worry about performance at this stage.
The second block of code is better.
The line
printf("cloneString = %s\n", clone);
there will never get executed since there a return statement before that.
To make your code a bit more readable, change
while
(
*clone++ = *string++
, --Length
);
to
while ( Length > 0 )
{
*clone++ = *string++;
--Length;
}
This is probably a better approach to your problem:
#include <stdio.h>
#include <string.h>
void cloneString(char *clone, char *string)
{
for (int i = 0; i != strlen(string); i++)
clone[i] = string[i];
printf("Clone string: %s\n", clone);
}
That been said, there's already a standard function to to that:
strncpy(const char *dest, const char *source, int n)
dest is the destination string, and source is the string that must be copied. This function will copy a maximum of n characters.
So, your code will be:
#include <stdio.h>
#include <string.h>
void cloneString(char *clone, char *string)
{
strncpy(clone, string, strlen(string));
printf("Clone string: %s\n", clone);
}
For years, I've gotten in to the habit of not using the value of a for loop iterator after the loop exits. I could have sworn that I did this, because it used to produce a compiler warning, but after I was challenged in a recent code review, I was proven wrong.
For example, I always did this (NOTE: our code standards prohibit the use of the "break" keyword):
int i, result;
bool done = false;
for (i=0; i<10 && !done; i++) {
if (some_condition) {
result = i;
done = true;
}
}
// Value of i may be undefined here
Now, obviously the result variable could be removed, if I can rely on the value of i. I thought that because of compiler optimization, you could not rely on the value of the loop iterator. Am I just remembering a phantom teaching? Or is this the standard (specifically regarding GNU C)?
There is nothing wrong in C89, C99, or C11 to access the iteration variable after the for statement.
int i;
for (i = 0; i < 10; i++) {
/* Some code */
}
printf("%d\n", i); // No magic, the value is 10
From C99, you can use also a declaration as the first clause of the for statement, and in that case of course the declared variable cannot be used after the for statement.
Different languages have different rules. In Pascal, the compiler is allowed to optimize away storing the loop index after the final increment, so it might be the first loop-terminating value or it might be the last valid value.
There are plenty of usage cases where the for loop is used for nothing else but advancing the iterator. This can be seen in some implementations of strlen (though admittedly there are other ways to do strlen), and other sorts of functions whose goal it is to find a certain limit:
/*find the index of the first element which is odd*/
for (ii = 0; ii < nelem && arry[ii] % 2 == 0; ii++);
As mentioned, the point of confusion may come from constructs where the iterator itself is defined within the for statement.
In general for statements are very very powerful, and it's unfortunate that they're usually never utilized to their full potential.
For example, a different version of the same loop can be written as follows (though it wouldn't demonstrate the safety of using the iterator):
#include <stdio.h>
int main(void)
{
int cur, ii = 0, nelem, arry [] = { 1, 2, 4, 6, 8, 8, 3, 42, 45, 67 };
int sum = 0;
nelem = sizeof(arry) / sizeof(int);
/* Look mom! no curly braces! */
for (
ii = 0;
ii < nelem && ((cur = arry[ii]) %2 == 0 ||
((printf("Found odd number: %d\n", cur)||1)));
ii++, sum += cur
);
printf("Sum of all numbers is %d\n", sum);
return 0;
}
In this particular case, it seems like a lot of work for this specific problem, but it can be very handy for some things.
Even though the value of that for loop's control variable is well defined, you might have been told to avoid using the for loop's control variable after the for loop because of the way scoping of that variable is handled, and especially because the handling has changed of the history of C++ (I know this question is tagged "C", but I think the rationale for avoiding using for loop control variable after the loop may have origins in this C++ history).
For example, consider the following code:
int more_work_to_do(void)
{
return 1;
}
int some_condition(void)
{
return 1;
}
int foo()
{
int i = 100;
while (more_work_to_do()) {
int done = 0;
for (int i = 0; i < 10 && !done; i++) {
if (some_condition()) {
done = 1;
}
}
if (done) return i; // which `i`?
}
return 1;
}
Under some old rules of scoping for the i declared in the for loop, the value returned on the statement marked with the comment "which i" would be determined by the for loop (VC++ 6 uses these rules). Under the newer, standard rules for scoping that variable, the value returned will be the i declared at the start of the function.
While I can't possibly know how your habit came to be, I can tell you how my habit to do the same did. It was by seeing code like this:
for (i=0u; (i<someLimit) && (found != TRUE); i++)
{
if (someCondition) found = TRUE;
}
foundIndex = i-1;
Basically, code like this is written when the break keyword is disallowed by some coding rules, e.g. based on MISRA. If you don't break out of the loop though, the loop will usually leave you with an "i" which is off by one from what you care for.
Sometimes, you can even find this:
for (i=0u; (i<someLimit) && (found != TRUE); i++)
{
if (someCondition) found = TRUE;
}
foundIndex = i;
This is just semantically wrong and can be found when the "forbid break keyword rule" is introduced into an existing code base which is not sufficiently covered by unit tests. May sound surprising, but it's all out there...
In the program I have pasted below, I was just wondering why the pointer "p" was initialized within the for loop? I am used to reading the conditions of a for loop as: starting from this value of a variable; until it reaches this value; increment it by this much. So it seems strange to have another variable that does not determine the ending condition and is not being incremented during each iteration in there at all.
I would have just put p=&a[0]; above the for loop and left the rest. Is this just a stylistic thing or are there differences in the way things are processed depending on where you initialize p? Is one way preferred over the other?
#include <stdio.h>
#define PRD(a) printf("%d", (a) )
int a[]={0, 1, 2, 3, 4};
int main()
{
int i;
int* p;
for (p=&a[0], i=0; i<=4; i++) PRD(p[i]);
return 0;
}
This appears to be just a style thing. I would probably have also put the initialisation of p outside the for statement, since cramming everything in there makes the code harder to read. (Because the pattern of that for loop is different from what you might usually expect, an experienced programmer will have to stop, back up, and think about what's in there before it will make sense. I initially thought there were four clauses in the for control statements until I noticed that the first separator was a comma.)
Writing the code like this (instead of initialising p outside the loop) will have no effect on performance.