Giter VIP home page Giter VIP logo

bgc's Introduction

Hi there! I'm a general enthusiast of computing! I write books and blogs and I teach and code.

🏍️ 🥾 💻 👾 ☠️ 🥁 🎹 🎸 🐐

bgc's People

Contributors

alexeikm avatar amirkhaki avatar amyshackles avatar anordin95 avatar atiedebee avatar bckempa avatar beejjorgensen avatar bondadam avatar ergoold avatar evgenhi avatar fransnylund avatar furkan avatar johnoro avatar mslaursen avatar mt-gitlocalize avatar philj56 avatar poorchop avatar ronak69 avatar sereneinserenade avatar smnbajwa avatar stefantalpalaru avatar stevewillson avatar tinez avatar trevcan avatar tverghis avatar verhovsky avatar willhertz avatar winspool avatar xiretza avatar zmitchell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bgc's Issues

11.3 void Pointers :: Interrogation

This is something that I am still puzzled about after reading the chapter.
You discuss functions with void pointer type definitions.
The example shows that you can convert void pointers to other pointers before manipulating them.
If you know the types of pointers in the first place, why would you not want to declare it in the types of the calling function?
If you can add a line or two on why you would want to declare void pointers and coerce them immediately to another pointer, that would be amazing.
(If for any reason you don't have the time or don't think it makes sense, feel free to close without explaning, I just thought you might want to know).

39.4 free in the first code example

I copied here your first code example with the race condition

#include <stdio.h>
#include <threads.h>

int run(void *arg)
{
    int i = *(int*)arg;

    free(arg);

    printf("THREAD %d: running!\n", i);

    return i;
}

#define THREAD_COUNT 5

int main(void)
{
    thrd_t t[THREAD_COUNT];

    int i;

    printf("Launching threads...\n");
    for (i = 0; i < THREAD_COUNT; i++)
        thrd_create(t + i, run, &i);   // <--- NOTE THIS

    printf("Doing other things while the thread runs...\n");
    printf("Waiting for thread to complete...\n");

    for (int i = 0; i < THREAD_COUNT; i++) {
        int res;
        thrd_join(t[i], &res);

        printf("Thread %d complete!\n", res);
    }

    printf("All threads complete!\n");
}

I think it would be good to add a comment next to the free(arg) inside the run function.
My initial thought was that this would free i and cause undefined behavior.
I'm still not sure why we need to free(arg) though. arg is just a pointer to i that we created. We never malloc for it. Would it not live on the stack?

19.2 Simple Macros: explaining a little further macro use

You mention in the chapter that macro can be used to define constants.
What is the differences with just using a cont float pi = 3.14. Why would you choose one vs the other?
What are the tradeoff, advantages, disadvantages?
Maybe something around memory allocation? Or maybe it's just convention?

GitHub repo lacks straightforward COPYRIGHT file

While the published PDFs and web version of this document clearly state

v0.6.8, Copyright © May 4, 2021

This GitHub repo lacks a COPYRIGHT or LICENSE file, so passers by may not be entirely aware of their rights. Those that are conscious like me, may be weary of cloning the repo so as to not violate copyright.

I suggest a new COPYRIGHT file with something like this, but I am not a lawyer:

Copyright © 2021 Brian Hall
All Rights Reserved
Permission is granted to copy this work for the purposes of personal use and translation to other languages

Again I am not a lawyer, if you want professional advice on what to put in the file, contact a lawyer.

It's also possible you don't really care about this stuff and would like to leave it as is, which is fine too!

15.3.2 The Usual Arithmetic Conversions -> add comments if possible

In that section you have the following piece of code.

int x = 3 + 1.2;   // Mixing int and double
float y = 12 * 2;  // Mixing float and int

even though the rules are detailed thereafter, I think it would be nice to have what is happening spelled out clearly. For example

int x = 3 + 1.2;   // Mixing int and double
// 3 gets converted to float
// 4.2 gets converted to int
// x is 4

// float y = 12 * 2; // Mixing float and int
// 24 gets converted to float
// y is 24

Just a suggestion.

40.11 a note about sscanf

There is a footgun about sscanf that has been mediatised on HN recently.
Basically sscanf will call strlen so the complexity is linear in the string length. If you use this for a parser and repeatedly call it then you have quadratic complexity.
I'm not sure how it should be integrated, but i feel a mention here might be helpful
Here are the references to the mention of the problems
https://www.mattkeeter.com/blog/2021-03-01-happen/
https://news.ycombinator.com/item?id=26302744
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/

6.6.1 Getting a Pointer to an Array -> typo: gives is

In section 6.6.1 you have the following sentence

But hold on a second–isn’t p an int*? And *p gives is 11, same as a[0]? Yessss.
Maybe remove the is in gives is?
Or add a What as in And what *p gives is 11, ...?

29.3 Writing Signal Handlers : example of using the return function

First of all, that chapter is really good. I really liked the way you go through explaining the function signature. I had missed the subtlety completely!

That asks another question though, how would you use that return function from the signal?
(feel free to skip this one as you mention later that signal is not used that much anyway).

Which leads to the second question. You mention that signal is not used. There is a brief mention about the sigaction. I know it's only valid for unix, but since this is a chapter about signal handlers, an example would be amazing.

33.2 static for Arrays in Parameter Lists: typo

And then the compiler can make certain cone optimization, safe in the knowledge that you, the programmer, will always do the right thing.

I think you meant core optimization.
Also maybe add a s at the end of optimization?

39.7 Mutexes: use of static keyword

The first time you define a mutex you use

#include <stdio.h>
#include <threads.h>

static mtx_t serial_mtx;     // <-- MUTEX VARIABLE

no need for the static here right?
Maybe i'm missing something

gcc on MacOS

Just want to point out that gcc can in fact be used on macOS. All you have to do is install MacPorts or Homebrew and then install the version of gcc you want through them. Also macOS is a version of Unix and writing C code is fairly similar on macOS and Linux (and I’m assuming the BSDs since they share things like the kqueue api).

40.3 tmpfile(): be curious

In the chapter you have the following sentence

(Specifically, tmpfile() unlinks the file right after it opens it. If you don’t know what that means, it won’t affect your tmpfile() skill, but hey, be curious! It’s for your own good!)

a link to a resource would be great.
Would the following be appropriate?
https://man7.org/linux/man-pages/man2/unlink.2.html

27.10 Parse State, Restartable Functions: variable name

I have to say i'm a little confused by then naming of variable in that example

// mbsrtowcs() modifies the input pointer to point at the first
    // invalid character, or NULL if successful. Let's make a copy of
    // the pointer for mbsrtowcs() to mess with so our original is
    // unchanged.
    const char *invalid = mb_string;

Why call it invalid in this case?
I initially thought you wanted to show a case where the conversion is failing. Instead it's a case where the conversion succeeds.
I personally think that the invalid case would be interesting.
If you keep the valid case, how about showing a multi-threaded example? (I understand you might not want to digress too much).
Otherwise, how about renaming the variable maybe_invalid or even maybe_invalid_but_valid_here
(I understand C likes to name variable with way too few characters, so feel free to reject those on those grounds)

31.7 goto and Variable Scope: typo?

The warning in the paragraph says

warning: ‘a’ is used uninitialized in this function

but the code only defines an x variable.
It seems to me that the warning should say x

30.4 Passing One-Dimensional VLAs to Functions: rename function add

in that paragraph you have the function add

int add(int count, int *v)
{
    int total = 0;

    for (int i = 0; i < count; i++)
        total += v[i];

    return total;
}

I found it a little confusing. How about naming it total, sum, sum_up_to, or total_until?
i thought add was going to add something to the elements of the array.
I understand this is highly subjective, and that naming is hard!

31.2 Labeled continue: suggestion: triple nested loop

In the chapter you show an example of a goto statement as a labeled continue.
In order to achieve the same functionality you would use a break in this case, I think.
One thing that you could not achieve with a simple break would be to continue in the outer look of a 3 nested deep loop.
With such an example, there would be no other way than goto.
Another example would be to continue outside of the double nested loop (you already have this one further down as an example of a labeled break)

In rust they have a seldom talked about feature to break out of a double loop, that is similar.

13.2 File Scope -> prints 110

on that chapter, you have the following code

#include <stdio.h>

int shared = 10;    // File scope! Visible to the whole file after this!

void func1(void)
{
    shared += 100;  // Now shared holds 110
}

void func2(void)
{
    printf("%d\n", shared);  // Prints "10"
}

int main(void)
{
    func1();
    func2();
}

I tested this and it prints 110 not 10.
Maybe you meant something different?

Enable Discussions if possible please

Hey @beejjorgensen, I hope you are doing well.

Is it possible to enable / activate Discussions so we can start Q and A?

This way we can participate as a community and provide valuable feedback based on personal and professional experience while producing qualitative content.

Thoughts?

9.6 Binary File I/O -> detail a bit sizeof bytes

In 6.2 you say that getting the size of an array is impossible.

In 9.6 you use the following code

 unsigned char bytes[] = {5, 37, 0, 88, 255, 12};

    fp = fopen("output.bin", "wb");  // wb mode for "write binary"!

    // In the call to fwrite, the arguments are:
    //
    // * Pointer to data to write
    // * Size of each "piece" of data
    // * Count of each "piece" of data
    // * FILE*

    fwrite(bytes, sizeof(char), sizeof bytes, fp);

You give an explanation after, but just reading it, makes me think that the sizeof operator can give you the size of an array. To be clear, i would expect something to say why sizeof bytes returns 6.

This might be my own interpretation of things that is wrong. Feel free to close the issue if you think it's irrelevant.
Just thought you might want to know.

Missing "(" on sizeof operator

On Page 17 of the book in pdf - section 3.2.7 The sizeof Opeartor - an example is given using sizeof operator:

int a = 999;

printf("%zu\n", sizeof a); // Prints 4 on my system
printf("%zu\n", sizeof(2 + 7)); // Prints 4 on my system
printf("%zu\n", sizeof 3.14); // Prints 8 on my system
// If you need to print out negative size_t values, use %zd

the first line of sizeof operation requires "(" before a in order to work. Thus, the proper code should be:

int a = 999;

printf("%zu\n", sizeof (a)); // Prints 4 on my system
printf("%zu\n", sizeof(2 + 7)); // Prints 4 on my system
printf("%zu\n", sizeof 3.14); // Prints 8 on my system
// If you need to print out negative size_t values, use %zd

Cheers,

39.8: VALUE_MAX

in the condvar chapter, you have a variable named VALUE_MAX
which isn't the maximum of the value but rather the max count.
How about naming it VALUE_COUNT
or if you really want to be clear VALUE_MAX_COUNT

20.6.1 Non-Adjacent Bit-Fields: a little more explanation

In the chapter you have

    struct foo {            // sizeof(struct foo) == 12 (for me)
        unsigned int a:1;
        unsigned int c:1;
        unsigned int b;
        unsigned int d;
    };

adding an explanation of why it is 12 would be great. It wasn't obvious to me at all.

  • a and c get packed together into 4 bytes
  • b is an unsigned int so 4 bytes
  • same with d
  • the total is 12 bytes

Why are VLAs banned from the linux kernel

In the VLA chapter you mention that you will explain later why VLA are banned in the linux kernel.

Using goto and longjmp, you mention some caveats.

You also mention that longjmp is rarely used.
goto has been frowned upon a lot, so it wouldn't seem like the reason why VLA would be banned.
I'm not sure why, but would be interested to have a clear answer (even 1 or 2 lines somewhere).

[minor] license typo

The License states the following:

Beej's Guide to Network Programming is Copyright © 2021 Brian "Beej Jorgensen" Hall.

Isn't this Beej's Guide to C Programming ?

39 lock free algorithm and concurrency

First of all, thanks for a great chapter on concurrency!

I'm wondering if you could consider talking about lock free algorithms for concurrency.
stuff like memory barriers, READ_ONCE, smp_store_release, smp_load_acquire, CAS and the like.
I know this stuff is not simple, just for you to consider. I would personally be super interested.

39.4 Creating and Waiting for Threads: NOTE THIS

in that chapter you have a // NOTE THIS
I think what you want to highlight is the pass by reference &i to show later the race condition.
On the line with the comment the expression is quite long. Therefore the THIS is not immediately obvious.
How about changing // NOTE THIS to //NOTE THE &i

39.8: use of `static`

in the condvar code you have

static int value[VALUE_MAX];  // Shared global
static int value_count = 0;   // Shared global, too

they are file scope, so perhaps no need for static here?

12.5 Changing Allocated Size with realloc() :: sizeof(*p)

That call

float *p = malloc(sizeof *p * 20);

Is a little surprising. p hasn't been defined before and your are using itself in its own definition.
Adding a line on why it's valid and that it would even work if p was assigned to NULL (which you do several lines after).
I naively thought that perhaps the pointer is being dereferenced, that is why it would work (after doing some research, I understand now that it's not).

Just a thought.
(Please take this comment as, if it makes sense to you and if you have time, but demands no explanation or justification on your part)

18.1 Command Line Arguments -> include an explanation

In the section you have the following program

int main(int argc, char **argv)
{
    int total = 0;

    for (int i = 0; i < argc; i++) {
        int value = atoi(argv[i]);  // Use strtol() for better error handling

        total += value;
    }

    printf("%d\n", total);
}

I would like to have one line of explanation around the tradeoff you went through when designing that program.
Something like.

  • Instead of starting from index 1, I decided to start from index 0 for the program to be more concise. Starting form 1 would mean adding a line to explicitely the case of 0 arguments
  • The other advantage of starting from 0 is that the atoi function will just convert the name of the program to 0.

Your reasoning might have been different. That decision to start from 0 is a little surprising (to me), adding a sentence to explain, would not hurt, I think.

40: errno

There is only a brief mention of errno in chapter 36 and one in chapter 40
Both of those mentions don't really explain what it is or how it is useful.
I would love to have an explanation somewhere.
(let me know if I've missed it)

Improvement: 3.2.1 The sizeof Operator -> Define %zu before using it

Hey,

Amazing guide (I haven't read all of it yet), I love how it doesn't assume any prior knowledge and goes through everything.

One tiny detail is that in part 3.2.1 The sizeof Operator, you use printf with %zu. How about giving a brief definition about it? You've defined %s %d and %f previously.

Thanks again for the great guide!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.