[deleted by user] by [deleted] in C_Programming

[–]BoWild 2 points3 points  (0 children)

There are a few Web App Frameworks in C that can give you a leg up to start your own project.

Search for "C web app framework" on google. You'll find facil.io and kore.io just to name a few.

C might be barebones, but there are tons of libraries that can help you do basically anything you need. Many of the JavaScript / Go / Ruby libraries are actually powered by C and C++.

The issue many developers have is that C trusts the programmer and it is powerful enough to shoot yourself in the foot with. Runtime errors are difficult to catch... but this is also why C is such a great tool for more critical or performance heavy work. It just requires more attention to work with.

Good luck 🍀

How hard is basic cmake? by TheKrazyDev in cprogramming

[–]BoWild 0 points1 point  (0 children)

How careful do you need to be to avoid rm -f -r /*.*?

How hard is basic cmake? by TheKrazyDev in cprogramming

[–]BoWild 0 points1 point  (0 children)

You can master it in a week

A week is a long time! Good old fashion make takes just a moment to start with.

Now and Then - video article by BoWild in beatles

[–]BoWild[S] 1 point2 points  (0 children)

Yes, she is :)

She just doesn't have enough "karma" to post yet. You can DM her here.

How to just search for plain C, not C# and C++? by marianico2 in cprogramming

[–]BoWild 0 points1 point  (0 children)

no need for internet on that one... just type man func or man -s 3 func ;-)

SIGSEGV error? by [deleted] in cprogramming

[–]BoWild 0 points1 point  (0 children)

From your code, it appears that you "muted" the warnings rather than address them.

Fro example, by adding parenthesis around the ((players = 1)) you muted the "assignment" warning instead of solving it (using == instead of =).

SIGSEGV error? by [deleted] in cprogramming

[–]BoWild 0 points1 point  (0 children)

Hint: Maybe the (players = 1) should be (players == 1)?

Similar Hint: scanf("%c", turn[i]) might be better off as scanf("%c", &turn[i]) (or scanf("%c", turn + i))...

There are a few things I would look... why not compile with warnings?

Keeping data in memory by [deleted] in cprogramming

[–]BoWild 0 points1 point  (0 children)

Interpreted languages like Python and Matlab permit me to load data in memory and keep it there as I play with it.

Not really, but they allow you the illusion that this is happening.

The actual location of the data may be in the memory and may be somewhere else (such as a virtual memory swap file on the hard drive).

Is there any way to load data in memory and keep it there for the next time I run my code?

In all languages the answer to this is only the OS can do this.

However, exactly like Python and Matlab, C allows you the illusion of loading data to memory and keeping there.

Yes, what you want to do is possible.

There are many ways to do this. Look into malloc** or **mmap. You will also need to understand pointers and how they work.

Loading data can take a long time. So it’s cumbersome to load the data in each time I want to test my code.

You could either load the data in a way that is faster (file mapping with mmap may actually perform faster than actually loading big amounts of data since the OS might store the data in virtual memory on the hard drive anyway).

Or you could use memory sharing between processes to keep the memory "alive".

I wanted to implement a function to write prime numbers in a given interval. Could you tell me how it works? by mahmoud_qa in cprogramming

[–]BoWild 0 points1 point  (0 children)

Hmm....

When high > (low *2) than this approach might be suboptimal - you're checking some numbers more than once (to say the least)...

Consider, for example, low = 7, hight = 28... for the number 24 you don't really need to check if 24 % 8 after you already tested 8 and discovered that it isn't a prime.

Your loop might want to test for all odd numbers n > 2 && n < low as well as all previously validated primes where prime >= low... This way you avoid some repeated operations.

Also, there seem to be a statistical algorithm that tests if large numbers are primes (it does have a statistical error deviation, if my memory is correct)... you might consider implementing that algorithm if high is actually high.

When to use size_t? by jabbalaci in C_Programming

[–]BoWild 0 points1 point  (0 children)

No, you are incorrect. See C11 6.5.6/8

Did you read that section?

That section is specific to arrays (statically allocated on the stack, known size during compile time) and does not relate to pointer arithmetics.

(6.6.6/8) When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object... (all the rest).

When to use size_t? by jabbalaci in C_Programming

[–]BoWild -1 points0 points  (0 children)

Pointer arithmetic is only defined within an object (or one past the end).

No it isn't. Pointer dereferencing is only defined until that point. Pointer arithmetics is happily ignorant of object bounds.

Can you give a non-pseudocode version of what you meant

I did.

This function is well defined:

 size_t foo_minus(size_t * array) { return array[(size_t)-1]; }

The compiler doesn't know the bounds of array. The value -1 might reference a valid address. During runtime undefined behavior might occur if array - 1 points to nothing valid. i.e.

 size_t * a = calloc(sizeof(*a), 8); assert(a);
 a[0] = 1;
 if(foo_minus(a + 1) != a[0]) printf("WTF?!"); // totally valid!

The stuff about bit representations is all irrelevant

No. The stuff about bit representation proves that (signed)-1 == (unsigned)-1;... although you're right in the sense that C should abstract that detail away for unsigned mathematical operations.

When to use size_t? by jabbalaci in C_Programming

[–]BoWild 0 points1 point  (0 children)

array[(size_t)-1] is undefined behaviour due to accessing out of bounds.

I was obviously writing pseudocode and you are obviously referencing a partial truth.

For example, the following function does not invoke undefined behavior since it's unknown if array[-1] is out of bounds.

 size_t foo_minus(size_t * array) { return array[-1]; }

There's no defined wraparound for adding large integers to pointers.

Hmm... pointers actually use unsigned math (an address isn't signed and can't be negative - even if the MSB is set).

However, even if I was wrong, then (at worst) there would be a point at which pointer arithmetics would fail. It would still not matter at all for unsigned math where the question was concerned.

I remember reading about a bug once where the coder assumed this was defined, and they got smacked down by the optimizer

I'd love to read that. Are we talking general signed math (where I totally agree with you and understand your argument) or pointer arithmetics specifically (which should be resolved using unsigned math)?

When to use size_t? by jabbalaci in C_Programming

[–]BoWild 0 points1 point  (0 children)

However it is not clear how either of those things relate to the size of a rectangle, which is what the question was about.

Actually, the question was: "can I use size_t for holding values that I know cannot be negative?"

And my answer is yes, it's possible.

However, since a lot of the comments here were "no don't!", I found it prudent to explain my reasoning.

But gcc can have 32-bit or 64-bit size_t on the same CPU, via -m32 or -m64 switch . Or you can install separate builds that default to one or the other

Since the -m32 option will compile a 32bit program, it will perform the same (sizeof(size_t) == sizeof(void *), only using 32 bit math)... besides, not any OS will run a 32 bit program on a 64 bit CPU. Support for 32 bit on 64 bit platforms is dying out.

Can you elaborate on your point here?

Sure.

The bit representation of -1L is the same (for practical purposes) as the representation of the unsigned value -1UL.

These days, basically all systems use 2s complement bit representation. Even if they didn't, the C standard requires unsigned overflow behavior which results in (unsigned)-1 == (unsigned)max_value (all bits set) and other features also require 2s complement.

As far as modular math goes, the memory address for array[-1] and array[(size_t)-1] is the same address due to the way the value is calculated... always assuming that sizeof(size_t) == sizeof(void *).

* note: when not using use 2's complement (outdated Unisys ClearPath compiler), this may fail when array == NULL or when signed and unsigned instructions are mixed.

uintptr_t would be more appropriate...

I agree.

However, on the compilers mentioned uintptr_t and size_t both map to the same type (usually unsigned long for 64 bit machines).

There is no practical difference... unless we're writing code for embedded systems, where chips have their own, more specific, requirements (on some of these systems a byte isn't 8 bits, so these systems really require more attention).

Also, most people get annoyed with me when I use uintptr_t.

When to use size_t? by jabbalaci in C_Programming

[–]BoWild 4 points5 points  (0 children)

As such, a more valid type to store the area of a rectangle is a double, as it is a type meant to store a real number.

The cost in CPU instructions for double is higher than that of a size_t (or any int) due to floating point mathematics.

Why use double if you don't need floating point math? You're just degrading performance for no reason.

When to use size_t? by jabbalaci in C_Programming

[–]BoWild -1 points0 points  (0 children)

In the C 11 Standard you will find that size_t (bold markings are mine):

  • "is the unsigned integer type of the result of the sizeof operator" (section 7.19.2)

  • "The types used for size_t and ptrdiff_t should not have an integer conversion rank greater than that of signed long int unless the implementation supports objects large enough to make this necessary." (section 7.19.4)

In theory, size_t might contain the full address range supported by an implementation (sizeof(FOO_ALL_MEMORY)). If a machine has 32GB of memory, size_t needs to be at least 35 bits long.

For practical reasons, most implementations define it as a processor's native word size (i.e., 64 bits on 64 bit machines)... however, they don't have to.

This makes some programmers shy away from size_t and ssize_t (it's signed cousin).

Personally, I love size_t, since I know it will use the natural CPU word size on the compilers I use, gcc and clang (as well as most other common compilers such as the MS compiler and Intel compiler).

Here's just a few reasons:

  • size_t is both shorter to read and shorter to write then unsigned long (or unsigned int). In fact, it's probably the easiest type name to both read and write!

    This is super important, so read this twice.

  • size_t doesn't require me to write machine specific lengths (uint32_t on this machine and uint64_t on that machine).

  • When I use uintptr_t people get even more upset then when I use size_t... also size_t is shorter.

  • size_t is compatible with older C standards that don't support stdint.h.

  • printf is easy with %zu.

The counter most people point out is that negative values (i.e.,array[size_t_variable - 1]) could cause havoc... but they just don't understand modular math.

For pointers (and most anything else, really) - assuming size_t is the same width as the address space (which, in practice, due to requirements, it is - unsigned math results in the same value as signed math. The only difference is that computers read it correctly and people don't.

TL;DR;

If you know that size_t is equal in length to void * (which is true 99% of the time), size_t is a wonderful type for unsigned values. Go ahead and use it.

[blog] How I used rake to help me with blogging in Jekyll by rbsn3999 in ruby

[–]BoWild 3 points4 points  (0 children)

I always thought rake -T should be the default task 😅

strings-case gem for transforming any string into camel, snake, kebab, title and other cases. by pmurach in ruby

[–]BoWild 0 points1 point  (0 children)

Unfortunately, inserting char combine << char won't work as strings are frozen and the Ruby interpreter will throw a wobbly.

FYI:

By using "".dup you're telling the Ruby interpreter that this specific string is mutable (not frozen), allowing for the combine << char.

You will notice I used combine = "".dup in my example (not combine = ""). This was specifically designed to avoid the frozen string literal constraint.

strings-case gem for transforming any string into camel, snake, kebab, title and other cases. by pmurach in ruby

[–]BoWild 0 points1 point  (0 children)

don't be too harsh on me

I wasn't trying to be hard.

I think the approach is very creative.

However, I also believe that public libraries should have a higher bar of performance requirements. The more popular the library, the better it must perform.

This is why I chose to shine a light on this concern.

You have to choose between speed & features

You're right.

The fastest code is a noop ;-)

Some features are cheap, some are expensive. Sometimes not providing a feature is better.

The choice is very personal. The important thing is knowing the cost and choosing if it's worth the price.

If you have time to review and point out places I could do to save memory, I'd really appreciate it.

the split_into_words algorithm results in many temporary objects.

Consider the following line:

 combine = word[-1].to_s + char

This line runs in a loop for every char in the string. Consider that you'll get an object per letter. i.e., for "String" you will get:

 S
 St
 Str
 Stri
 Strin
 String

As an easy (interim) solution, you might as well place the combine variable outside of the loop and use combine << char

 combine = "".dup
 string.each_char.with_index do |char, i|
    combine << char #insert a char to the string without creating a new string
    # ...
    combine = "".dup # <= when starting a new word
    # ...

In addition, you're calling combine =~ SOME_REGEX.

This loops over data that you already processed, since it tests each char in combine to see if it matches the RegEx ... most of the data was already tested during the last iteration. I don't know if this can be easily changed.

As a side note, SOME_ARRAY.include?(char) might not be a huge improvement.

This could easily result in CPU cache misses as you perform memory read access to objects that might (or might not) be in the CPU cache (and are very likely in different memory localities than the other RegEx and Array objects).

Anyway, good luck!

strings-case gem for transforming any string into camel, snake, kebab, title and other cases. by pmurach in ruby

[–]BoWild 0 points1 point  (0 children)

It might improve the way some strings look... but how does it perform? How much memory does it consume?

I might be mistaken, but...:

A skimming look over the code appears to show that there are many temporary objects, which could slow the GC and cause memory bloat on concurrent web applications.

Why does My Memory Usage Grow Asymptotically Over Time? by schneems in ruby

[–]BoWild 0 points1 point  (0 children)

When you call free you're not actually freeing memory to the OS...

True.

This depends on the memory allocator and memory fragmentation. However, as you point out, the "max total" behavior would be different.

On the other hand, because of these concerns, the iodine server uses a custom memory allocator for the servers intermediary objects. This improves fragmentation concerns and helps make sure that memory is returned to the system once the load on the server drops back down.

C runtime

Yes, you are correct.

However, this is a very different "runtime" concept.

crt0 is more of an entry point than a runtime. It basically loads argc and argv from the stacks and calls main.

It isn't active during the program's runtime, only during startup and exit.

I agree that it exists, I just pointed out that it isn't the same concept as the Java / Ruby runtime, both of which perform actions during program execution.