I'm working with strings in C as character arrays, and I'm trying to ensure that I can dynamically pass values into my for loops.
The following code works, no problem:
for (int i = -6; i < 11; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
In fact, this code works, too:
for (int i = -strlen(fragments[2]) + 1; i < 11; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
But for some reason, this code doesn't print ANYTHING:
for (int i = -strlen(fragments[2]) + 1; i < strlen(fragments[1]); i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
I have checked the values for both -strlen(fragments[2]) + 1 and strlen(fragments[1]) just before the loop and they check out to -6 and 11 respectively. Clearly the loop works when I place those values directly into their places, but when I replace the second one with the strlen calculations, it breaks and I can't figure out why for the life of me. Help?
Edit
OverlapStrength takes its arguments as constants so I can't change them, so I'm pretty sure I'm not changing the fragments as I go. Here's the method declaration:
int OverlapStrength(const char one[], const char two[], int startOne, int startTwo)
The contents of the fragments shouldn't be important, but they're simply strings that I'm trying to piece back together from overlapping fragments. I have already checked that my fragments are all coming out properly and that their lengths are computed properly when done outside of declaring this loop.
strlen returns value of type size_t, which is probably a typedef for unsigned int for your case. Then you are comparing a signed int (i) and unsigned int (strlen(...)). C decides then to cast your signed value to an unsigned type (because of default type promotions). -6 converted to unsigned int is 4294967290, therefore your comparison is false, so the loop ends.
To fix this, you can for example cast strlen to a signed value, e.g.:
i < (int) strlen(fragments[1])
In a for-loop, the codition (the i < strlen(fragments[1]) part) gets evaluated on every iteration. If OverlapStrength changes the value of fragments[1] to something less than i, the loop will abort.
To fix this, use a constant:
int loopUntil = strlen(fragments[1]);
for (int i = -strlen(fragments[2]) + 1; i < loopUntil; i++) {
int test = OverlapStrength(fragments[1], fragments[2], i, 0);
printf("%d\n", test);
}
Related
I have a problem with my C-program and I think I need some help.
My program is doing some calculations using multiple threads. Every thread runs a method with only one parameter and in the end returns an integer.
Now, to complete my calculation, it is necessary to take the sum of all sub-calculations, that means the sum of all integers returned by the threads.
But somehow, that result is not correct. I think I made a mistake in getting all returned integers from the threads.
Here is my code:
//creating the threads (with splitArray[] as an array of pointers to other arrays)
pthread_t threads[n];
for (int i = 0; i < n; i++) {
pthread_create(&threads[i], NULL, (void * )(countPrime), (void * )splitArray[i]);
}
//getting the results of the threads
int numPrimes = 0;
int save;
for (int i = 0; i < n; i++) {
pthread_join(threads[i],(void **) &save);
numPrimes = numPrimes + save;
}
This is the method every given to every thread:
int countPrime(int array[]) {
int numPrimes = 0;
for (int i = 0; i < size; i++) {
//checking if array[i] is a prime number
if (isPrime(array[i])) {
numPrimes++;
}
}
return numPrimes;
}
Have I made a mistake? I am new to C and so I am not really confident about working with pointers, which seems to be necessary in this case.
Thanks a lot :)
The thread function is supposed to be returning a void * pointer, and on a 64-bit machine void * is typically 64 bits wide, while int is typically only 32 bits wide.
When you return a 32-bit value from a function that is expected to return a 64-bit value, what will the extra 32 bits have for value? That's unknown and your code exhibits undefined behavior because of this.
To solve your problem (as I think it might be) you need to update the thread function to return the correct type (void *) and do some casting to make sure the value you return is of the correct type and size:
void *countPrime(int array[]) {
...
return (void *) (intptr_t) numPrimes;
}
Then when you fetch the value, you need to use the correct types as well, and use the opposite casting:
void *result;
for (int i = 0; i < n; i++) {
pthread_join(threads[i],&result);
numPrimes = numPrimes + (int) (intptr_t) result;
}
Note that returning a non-pointer value like this (as well as passing a non-pointer value as argument to the thread function) is almost the only case where most people would agree that such casting is okay. Otherwise, it generally never is.
I got stuck in a univ project as follows:
I was doing it before I knew the format of the input, so I started reading it with %s, and it was a char[32].
Then when the project was released, I realized I needed to read the input as int.
So now I started to read it as int and now I don't want to make again all other functions I made, and they are receiving the arguments as an array of chars (char[32]).
So I made a function to convert the int value to int*, because I can't return char[32]. Hence I did, on main, a simple for to pass the values in int* to char[32]. The problem is that, when I print it on main, I see exactly the same values, but when I pass this new char[32] to my functions, I get a bug now. I guess my problem is because of '\0' or something like this.
A simple demonstration is below:
int* convert_dec_to_bin(int n){
printf("\n");
int i, j, k;
int *bits;
bits = (char*)malloc(32*sizeof(int));
for(i = 31, j = 0; i >= 0; --i){
printf("%d", n & 1 << i ? 1 : 0);
if(n & 1 << i){
bits[j] = 1;
}else{
bits[j] = 0;
}
j++;
}
printf("\n");
return bits;
}
int main(){
int i, k, instructionNameInt;
char type;
int *bits;
char bitsC[32];
//char instructionBinary[32]; I was reading like this before, ignore this line
int instructionBinary; //Now I read like this
scanf("%d", &instructionBinary);
bits = convert_dec_to_bin(instructionBinary); //This is a function where I pass the int decimal input to 32 bits in binary as int*.
//Making probably the wrong conversion here, I tried to put '\0' in the end but somehow I failed
for(k = 0; k < 32; k++){
bitsC[k] = bits[k];
}
printf("\n");
type = determine_InstructionType(bitsC);
printf("TYPE: %c\n", type);
instructionNameInt = determine_InstructionName(bitsC, type);
And several other functions...
Can someone light me up how can I fix it? I spent several hours and still didn't achieve to pass this correctly to an array of chars.
I guess this is one of the classical questions.
As far as I know comparing unsigned and signed int are performed using unsigned arithmetic, which means that if length = -1 = unsigned max of 32 bits.
The code can be fixed by either declaring length to be an int, or by changing the test of the for loop to be i < length.
Declaring length to be an int, it's easy to understand, but changing the loop to be i < length not really easy.
If we have the following situation: 5 < -1 which if performed using unsigned arithmetic, in my computer yields 5 < 4294967295, how can this be a solution, it seems like it will access undefined elements.
Code
float sum_elements(float a[], unsigned length)
{
int i;
float result = 0;
for (i = 0; i <= length-1; i++)
result += a[i];
return result;
}
Consider the condition.
i <= length-1
As you mentioned, if length is zero then you will enter into a situation like 5 < 4294967295.
Changing the condition to "i < length" will prevent this.
Also changing type of variable "i" to "unsigned" makes sense because (a) it is array index. (b) you are comparing it with an "unsigned".
So I would prefer this code.
float sum_elements(float a[], unsigned length)
{
unsigned i = 0;
//float result = 0.0; //Refer comment section.
double result = 0.0;
for (i = 0; i < length; i++)
result += (double)a[i];
return result;
}
Option #1:
for (i = 0; i <= (int)length-1; i++)
Option #2:
for (i = 0; i+1 <= length; i++)
Option #3:
for (i = 0; i < length; i++)
It's your compilator job's, when he creates he's parser lexer, he uses a table for your variables. If he saw something like :
float a = b + 60
60 will be cast in 60.0 by your compilator.
I think this is the same thing here:
(unsigned int)length = (unsigned int)length (int)-1
becomes:
(unsigned int)length = (int)length (int)-1;
If you want a proper arithmetic comparison, you should use the flag -Wextra
A pedantic <= compare of and int <= unsigned would test for negative-ness first.
for (i = 0; i < 0 || ((unsigned) i) <= length-1; i++)
Removing the -1 helps to avoid overflow.
for (i = 0; i < 0 || ((unsigned) i) < length; i++)
A good compiler will likely optimize the code so 2 compares are not actually in the executable.
If -Wsign-conversion or its equivalent compiler option is not used, drop the cast for cleaner code #R..
for (i = 0; i < 0 || i < length; i++)
As well commented by #chqrlie the compare may perform well but subsequent operations on i may be a problem. In particular when i == INT_MAX, the i++ is UB.
Better to use size_t (an unsigned type) for array size computation and indexing.
float sum_elements(float a[], size_t length) {
float result = 0;
size_t i;
for (i = 0; i < length; i++)
result += a[i];
return result;
}
Your code will not perform as expected in 2 cases:
if length == 0, length - 1, computed using unsigned arithmetic, is a very large number and comparing i <= length - 1 will be always true because the comparison is also performed using unsigned arithmetics.
if length is larger than the maximum integer value, i can never reach such a value and although the comparison performed using unsigned arithmetic will work as expected, the indexing a[i] will be incorrect on 64-bit systems where the negative index will point outside the array.
The compiler correctly diagnoses a real problem. Using a signed type for i and comparing that to an unsigned length expression can lead to unexpected behavior. Correct the problem this way:
float sum_elements(float a[], unsigned length) {
double result = 0.0;
for (unsigned i = 0; i < length; i++) {
result += a[i];
}
return result;
}
Notes:
the types for length and i really should be size_t as this may be a larger type than unsigned.
the sum should be computed using double arithmetics, to achieve better precision than using float. Precision will be better, but still limited. Summing the array elements in a different order can produce a different result.
Lose the i variable, to save a little stack space and make the function faster.
float sum_elements(float a[], unsigned length)
{
float result = 0;
while (length--)
result += *a++;
return result;
}
I want to declare a double type array dynamically, so here is my code
void function(int length, ...)
{
...
double *a = malloc(sizeof(double) * length);
memset(a, 1, sizeof(double) * length);
for (int i = 0; i < length; i++)
{
printf("%f", a[i]);
}
...
}
When I pass a length of 2, the code does not print all 1s. It just prints the following:
7.7486e-304
7.7486e-304
So, what should I do to fix it?
memset sets bytes. You're trying to set doubles. Just loop from 0 to length and set each one to 1.0:
for (int i = 0; i < length; i ++)
{
a[i] = 1; // or 1.0 if you want to be explicit
}
You are confusing setting an array and setting the underlying memory that stores an array.
A double is made up of 8 bytes. You are setting each byte that makes up the double to 1.
If you want to initialise each element of the array to 1.0 then you can use a for(;;) loop or since you do seem to be using C++ you can use a container and use a constructor to initialise each element (if the constructor has the ability) or use an algorithm to achieve the same effect.
memset sets every byte of your array to 1 not every int or double element.
You are trying to set double values (maybe 8 or more bytes.) Your approach will only work for the number 0.0 as it happens to be represented with all bytes 0 on systems that use IEEE-754 floating point formats. Note that this would be non portable as the C Standard allows other representations for floating point values.
If a was pointing to an array of integers, your approach would work for 0 and -1 and some special values such as 0x01010101... But it would still be a non portable approach as it would fail or even invoke undefined behavior on exotic architectures with padding bits or non 2s complement integer representation.
The correct way to initialize the array is an explicit loop like this:
for (int i = 0; i < length; i++) {
a[i] = 1.0;
}
The compiler will likely compile this loop into very efficient code.
memset sets 1 byte at a time. Because of that, I recommend that you use a custom function to set an array of any data type to a valid value like the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void *g_memset(void *dst, void *val, size_t valSize, size_t count);
int main(void)
{
double x = 1.0;
double Array[50];
g_memset(Array, &x, sizeof(x), 20); /* set the 1st 20 elements to 1.0 */
for (int n = 0; n < 20; n++) {
printf("%.1lf ", Array[n]);
}
putchar('\n');
return 0;
}
void *g_memset(void *dst, void *val, size_t valSize, size_t count)
{
char *ptr = (char *)dst;
while (count-- > 0) {
memcpy(ptr, val, valSize);
ptr += valSize;
}
return dst;
}
You use memset to set your every bytes of array a.Double variable are 8 bytes,after memset array a every bytes is 1.
Function memset is for char array.
If you want init your array a you can use a loop(while/for).
int j;
for(j = 0;i < length;j++)
a[j] = 1;
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void check(int n, int arr[]);
int arr[] = {1, 2, 3, 4};
int i;
check(4, arr);
for (i = 0; i < 4; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
void check(int n, int arr[]) {
int i = 0;
int *p = 0;
while (i++ < n)
p = &arr[i];
*p = 0;
}
I need an explanation for the output.
The original question I was asked, and the expected multiple-choice answers, are:
Please post your actual code, not what you intended to type. Actually copy-paste your real code.
Because you typed it in wrong.
You either put extra {} in here:
while(i++ < n) {
p = &arr[i];
*p = 0;
}
or you used a comma instead of a semicolon:
while(i++ < n)
p = &arr[i],
*p = 0;
and so the assignment to zero ran every time.
Edit to add: Yep, you put extra {} which the original question didn't have. So in your code, the "*p = 0" executes every time round the while loop, whereas the original question the "*p = 0" only executes once and clobbers some random data that is one past the end of the array.
(By the way, the answer to the original question is actually "it is undefined behaviour; the program doesn't necessarily print anything. Valid behaviours include printing 1 2 3 4, printing 42 42 42 42, crashing, and formatting your hard drive.")
I'm not sure what choices you're talking about, however the cause of your output is here:
int i=0;
int *p=0
while(i++<n)
{
p=&arr[i];
*p=0;
}
Variable 'i' starts at 0 but you increment it before entering the loop so the first index of the array is ignored. You then set a pointer to array index 'i' and then immediately dereference the pointer and set the value to 0;
Because of this any array you pass will always retain its first value whilst every other value will be zero.
if you want to include the first index of the array you'd be much better off doing:
for (int i = 0; i < n; ++i)
{
// stuff
}
With this, 'i' is not incremented until after the code between the braces has been executed.
In check(), i gets incremented after the comparison, but before the first statement inside. So the zero (first) element of the array is never set to 0, like the rest are. arr's 1 stays 1, and 2, 3, & 4 each become 0.
EDIT:
The OP code has changed since the version I discussed. It's a whole new problem now.
Some things you should know.
First:
you should declare your functions if you declare/define them after main.
Second:
when you declare an Array, the array starts from 0 to n and not from 1 to n.
So, if you declare int arr = {1,2,3,4} then you have arr[0],1,2,3 and not arr[1],2,3,4.
Third:
you should avoid code like:
while (i++ < n) {
p = &arr[i];
*p = 0;
}
And use:
while (i < n) {
p = &arr[i];
*p = 0;
i++;
}
Fourth:
What exactly did you expected from this:
int *p = 0;
Anyway, you just try to access a memory location that not belong to you.